refactor: 迁移至 electron-vite 官方推荐目录结构

- electron/* -> src/main/* (主进程)
- electron/preload.ts -> src/preload/index.ts (预加载)
- src/electron-api.d.ts -> src/preload/index.d.ts (类型声明)
- src/* -> src/renderer/src/* (渲染进程)
- src/index.html -> src/renderer/index.html
- electron.vite.config.ts 简化为自动入口检测 (零配置)
- tsconfig.app.json -> tsconfig.web.json, 更新 includes/paths
- 构建产物 dist-electron/ -> out/ (修复 main/preload 输出覆盖 bug)
- 更新 package.json main 字段 + electron-builder files
- 更新 .gitignore + eslint ignores
- 更新 AGENTS.md 架构文档
This commit is contained in:
2026-07-10 23:46:34 +08:00
parent 157af4399f
commit eda30250c6
71 changed files with 112 additions and 127 deletions
+2 -2
View File
@@ -1,5 +1,5 @@
node_modules/
dist-electron/
out/
release/
dist/
*.log
@@ -15,7 +15,7 @@ yarn-error.log*
*.njsproj
*.sln
# Legacy codebase archived Vue 2 version, not part of v2 build
# Legacy codebase - archived Vue 2 version, not part of v2 build
legacy/
# Brainstorming artifacts
+88 -83
View File
@@ -6,10 +6,10 @@ Fork of [AnotherRedisDesktopManager](https://github.com/qishibo/AnotherRedisDesk
## Stack
- **Shell:** Electron 43 (`electron/main.ts`)
- **Preload:** `electron/preload.ts` (contextBridge, typed API)
- **Renderer:** Vue 3 + Pinia + Element Plus + Vue Router (`src/`)
- **IPC types:** `src/electron-api.d.ts` (ElectronAPI interface, global Window augmentation)
- **Shell:** Electron 43 (`src/main/index.ts`)
- **Preload:** `src/preload/index.ts` (contextBridge, typed API)
- **Renderer:** Vue 3 + Pinia + Element Plus + Vue Router (`src/renderer/src/`)
- **IPC types:** `src/preload/index.d.ts` (ElectronAPI interface, global Window augmentation)
- **Build:** electron-vite + Vite 6 + TypeScript 5
- **Redis client:** ioredis 5 (main process only)
- **Persistence:** electron-store + safeStorage (credentials)
@@ -18,7 +18,7 @@ Fork of [AnotherRedisDesktopManager](https://github.com/qishibo/AnotherRedisDesk
```bash
npm run dev # electron-vite dev (HMR, renderer on :5173)
npm run build # production build -> dist-electron/
npm run build # production build -> out/
npm start # preview built app
npm run build:unpack # build + electron-builder --dir
npm run build:win # build + electron-builder --win
@@ -30,80 +30,84 @@ npm run lint # eslint --fix
## Architecture
```
Electron main (electron/)
├── main.ts # Window creation, app lifecycle
├── preload.ts # contextBridge.exposeInMainWorld
├── ipc-handlers.ts # all IPC channel handlers
├── store.ts # electron-store (connections, settings)
├── credential.ts # safeStorage encrypt/decrypt
├── win-state.ts # window position persistence
── updater.ts # electron-updater (check/download/install)
└── redis/ # Redis service modules
├── index.ts # Unified export
├── connection.ts # connect, disconnect, isClientConnected
├── keys.ts # scan, delete, rename, ttl, batchDelete
├── string.ts # get, set
├── hash.ts # hscan, hset, hdel
├── list.ts # range, push, set, remove
├── set.ts # members, add, remove
├── zset.ts # range, add, remove
├── stream.ts # info, range, add, trim
├── server.ts # info, select, ping, slowlog
├── pubsub.ts # SUBSCRIBE/UNSUBSCRIBE
Electron main (src/main/)
├── index.ts # Window creation, app lifecycle
├── ipc-handlers.ts # all IPC channel handlers
├── store.ts # electron-store (connections, settings)
├── credential.ts # safeStorage encrypt/decrypt
├── win-state.ts # window position persistence
├── updater.ts # electron-updater (check/download/install)
── redis/ # Redis service modules
├── index.ts # Unified export
├── connection.ts # connect, disconnect, isClientConnected
├── keys.ts # scan, delete, rename, ttl, batchDelete
├── string.ts # get, set
├── hash.ts # hscan, hset, hdel
├── list.ts # range, push, set, remove
├── set.ts # members, add, remove
├── zset.ts # range, add, remove
├── stream.ts # info, range, add, trim
├── server.ts # info, select, ping, slowlog
├── pubsub.ts # SUBSCRIBE/UNSUBSCRIBE
├── commandLogger.ts # command execution log
└── format.ts # value decode/format detection
└── format.ts # value decode/format detection
Renderer (src/)
├── main.ts # Vue 3 bootstrap (Pinia, Element Plus)
── App.vue # Shell layout (TitleBar + Sidebar + MainArea + StatusBar)
├── env.d.ts # Vite client + *.vue / *.css module declarations
├── electron-api.d.ts # ElectronAPI interface + global Window augmentation
├── stores/
│ ├── app.ts # theme, fontSize, scanCount
├── connection.ts # connections CRUD, connect/disconnect, health check
── key.ts # key list, scan, tree view, selected key data
├── components/
├── TitleBar.vue # window controls
│ ├── StatusBar.vue # connection status, DB selector
│ ├── Sidebar.vue # keyboard shortcuts, dialog host
── ConnectionList.vue # search, import/export, new button
├── ConnectionCard.vue # single connection card
│ ├── NewConnectionDialog.vue # create/edit/test connection
│ ├── DbSelector.vue # database 0-15 dropdown
│ ├── MainArea.vue # tab host (Status/Keys/CLI/SlowLog/Settings)
│ ├── StatusView.vue # INFO dashboard with stat cards
│ ├── KeyBrowser.vue # split pane (KeyList + KeyDetail)
│ ├── KeyList.vue # pattern search, filter, SCAN, multi-select
│ ├── KeyDetail.vue # type dispatch, TTL, rename, copy
│ ├── StringEditor.vue # view/edit with JSON format
│ ├── HashEditor.vue # field table CRUD
│ ├── ListEditor.vue # paginated elements
│ ├── SetEditor.vue # member list
│ ├── ZsetEditor.vue # sorted set with scores
│ ├── StreamEditor.vue # stream entries
│ ├── CliView.vue # interactive terminal
│ ├── SlowLogView.vue # slow log table
│ ├── SettingsView.vue # theme, language, scan count
│ ├── MemoryAnalysis.vue # MEMORY USAGE scan & sort
│ ├── CommandLog.vue # command execution history
── ReJsonEditor.vue # JSON.GET / JSON.SET editing
├── i18n/
│ ├── index.ts # useI18n composable
── locales/
├── en.ts # English
── zh-CN.ts # 中文
├── ja.ts # 日本語
├── ko.ts # 한국어
└── de.ts # Deutsch
├── composables/
└── useKeyboard.ts # keyboard shortcut handler
├── styles/
│ ├── variables.css # CSS custom properties
│ └── global.css # global overrides
├── data/
│ └── commands.ts # Redis command definitions
└── utils/
└── binary.ts # hex ↔ buffer conversion
Preload (src/preload/)
├── index.ts # contextBridge.exposeInMainWorld
── index.d.ts # ElectronAPI type declarations
Renderer (src/renderer/)
├── index.html # Vite entry HTML
└── src/
├── main.ts # Vue 3 bootstrap (Pinia, Element Plus)
── App.vue # Shell layout (TitleBar + Sidebar + MainArea + StatusBar)
├── env.d.ts # Vite client + *.vue / *.css module declarations
├── stores/
│ ├── app.ts # theme, fontSize, scanCount
│ ├── connection.ts # connections CRUD, connect/disconnect, health check
── key.ts # key list, scan, tree view, selected key data
├── components/
│ ├── TitleBar.vue # window controls
│ ├── StatusBar.vue # connection status, DB selector
│ ├── Sidebar.vue # keyboard shortcuts, dialog host
│ ├── ConnectionList.vue # search, import/export, new button
│ ├── ConnectionCard.vue # single connection card
│ ├── NewConnectionDialog.vue # create/edit/test connection
│ ├── DbSelector.vue # database 0-15 dropdown
│ ├── MainArea.vue # tab host (Status/Keys/CLI/SlowLog/Settings)
│ ├── StatusView.vue # INFO dashboard with stat cards
│ ├── KeyBrowser.vue # split pane (KeyList + KeyDetail)
│ ├── KeyList.vue # pattern search, filter, SCAN, multi-select
│ ├── KeyDetail.vue # type dispatch, TTL, rename, copy
│ ├── StringEditor.vue # view/edit with JSON format
│ ├── HashEditor.vue # field table CRUD
│ ├── ListEditor.vue # paginated elements
│ ├── SetEditor.vue # member list
│ ├── ZsetEditor.vue # sorted set with scores
│ ├── StreamEditor.vue # stream entries
── CliView.vue # interactive terminal
│ ├── SlowLogView.vue # slow log table
│ ├── SettingsView.vue # theme, language, scan count
── MemoryAnalysis.vue # MEMORY USAGE scan & sort
├── CommandLog.vue # command execution history
── ReJsonEditor.vue # JSON.GET / JSON.SET editing
├── i18n/
├── index.ts # useI18n composable
└── locales/
│ ├── en.ts # English
├── zh-CN.ts # 中文
│ ├── ja.ts # 日本語
├── ko.ts # 한국어
│ └── de.ts # Deutsch
├── composables/
│ └── useKeyboard.ts # keyboard shortcut handler
├── styles/
│ ├── variables.css # CSS custom properties
│ └── global.css # global overrides
├── data/
│ └── commands.ts # Redis command definitions
└── utils/
└── binary.ts # hex ↔ buffer conversion
```
## IPC Channels
@@ -203,19 +207,20 @@ Renderer (src/)
## Build config
- `electron.vite.config.ts` defines three build targets: main, preload, renderer
- Main + preload output to `dist-electron/`; renderer to `dist-electron/renderer/`
- Entry points auto-detected: `src/main/index.ts`, `src/preload/index.ts`, `src/renderer/index.html`
- Build output: `out/main/`, `out/preload/`, `out/renderer/`
- electron-builder packages into `release/`
- Renderer dev server runs on port 5173
- Main/preload use `externalizeDepsPlugin()` to keep node_modules external
- `@renderer` alias resolves to `src`
- `@renderer` alias resolves to `src/renderer/src`
## TypeScript
- Root `tsconfig.json` references `tsconfig.node.json` (main + preload) and `tsconfig.app.json` (renderer)
- Node target (`tsconfig.node.json`) includes `electron/**/*` + `electron.vite.config.ts`
- App target (`tsconfig.app.json`) includes `src/**/*`
- Root `tsconfig.json` references `tsconfig.node.json` (main + preload) and `tsconfig.web.json` (renderer)
- Node target (`tsconfig.node.json`) includes `src/main/**/*`, `src/preload/**/*.ts`, `electron.vite.config.ts`
- Web target (`tsconfig.web.json`) includes `src/renderer/src/**/*`, `src/preload/**/*.d.ts`
- Both use `verbatimModuleSyntax` (type-only imports required) and `moduleResolution: "bundler"`
- `src/electron-api.d.ts` declares the `ElectronAPI` interface and augments global `Window`
- `src/preload/index.d.ts` declares the `ElectronAPI` interface and augments global `Window`
## Security
+5 -30
View File
@@ -5,44 +5,19 @@ import { resolve } from 'path'
export default defineConfig({
main: {
plugins: [externalizeDepsPlugin()],
build: {
outDir: 'dist-electron',
rollupOptions: {
input: {
index: resolve(__dirname, 'electron/main.ts')
}
}
}
},
preload: {
plugins: [externalizeDepsPlugin()],
build: {
outDir: 'dist-electron',
rollupOptions: {
input: {
index: resolve(__dirname, 'electron/preload.ts')
}
}
}
},
renderer: {
root: 'src',
build: {
outDir: resolve(__dirname, 'dist-electron/renderer'),
rollupOptions: {
input: {
index: resolve(__dirname, 'src/index.html')
}
}
},
resolve: {
alias: {
'@renderer': resolve(__dirname, 'src')
}
'@renderer': resolve(__dirname, 'src/renderer/src'),
},
},
plugins: [vue()],
server: {
port: 5173
}
}
port: 5173,
},
},
})
+1 -1
View File
@@ -13,7 +13,7 @@ const commonLanguageOptions = {
}
export default tseslint.config(
{ ignores: ['dist', 'dist-electron', 'release', 'coverage', 'node_modules'] },
{ ignores: ['dist', 'out', 'release', 'coverage', 'node_modules'] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommended],
files: ['**/*.ts'],
+3 -4
View File
@@ -9,7 +9,7 @@
},
"homepage": "http://git.jokul.space/Jokul/JRedisDesktop",
"type": "module",
"main": "./dist-electron/main.js",
"main": "./out/main/index.js",
"allowScripts": {
"electron": true,
"esbuild": true,
@@ -60,10 +60,9 @@
"output": "release"
},
"files": [
"dist/**/*",
"dist-electron/**/*",
"out/**/*",
"!**/*.map",
"!dist-electron/**/*.map",
"!out/**/*.map",
"package.json"
],
"publish": {
+1 -1
View File
@@ -22,7 +22,7 @@ function createWindow(): void {
icon: nativeImage.createFromPath(iconPath),
backgroundColor: nativeTheme.shouldUseDarkColors ? '#0f0f1a' : '#f8fafc',
webPreferences: {
preload: join(__dirname, '../preload.js'),
preload: join(__dirname, '../preload/index.mjs'),
contextIsolation: true,
nodeIntegration: false,
sandbox: false,
View File
+1 -1
View File
@@ -7,6 +7,6 @@
</head>
<body>
<div id="app"></div>
<script type="module" src="./main.ts"></script>
<script type="module" src="./src/main.ts"></script>
</body>
</html>
View File
+2 -2
View File
@@ -1,7 +1,7 @@
{
"files": [],
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.node.json" }
{ "path": "./tsconfig.node.json" },
{ "path": "./tsconfig.web.json" }
]
}
+1 -1
View File
@@ -19,5 +19,5 @@
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["electron.vite.config.ts", "electron"]
"include": ["electron.vite.config.ts", "src/main/**/*", "src/preload/**/*.ts"]
}
+8 -2
View File
@@ -1,6 +1,6 @@
{
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.web.tsbuildinfo",
"target": "es2023",
"lib": ["ESNext", "DOM"],
"module": "ESNext",
@@ -14,10 +14,16 @@
"moduleDetection": "force",
"noEmit": true,
/* Path alias */
"baseUrl": ".",
"paths": {
"@renderer/*": ["src/renderer/src/*"]
},
/* Linting */
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src"]
"include": ["src/renderer/src/**/*", "src/preload/**/*.d.ts"]
}