diff --git a/AGENTS.md b/AGENTS.md index 4036476..6c8dd4c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -7,10 +7,11 @@ Fork of [AnotherRedisDesktopManager](https://github.com/qishibo/AnotherRedisDesk ## Stack - **Shell:** Electron 33 (`src/main/index.ts`) -- **Preload:** `src/preload/index.ts` -- **Renderer:** Vue 3 + Element Plus + Vue Router (`src/renderer/`) +- **Preload:** `src/preload/index.ts` (contextBridge, typed API) +- **Renderer:** Vue 3 + Pinia + Element Plus + Vue Router (`src/renderer/`) - **Build:** electron-vite + Vite 6 + TypeScript 5 -- **Redis client:** ioredis 5 +- **Redis client:** ioredis 5 (main process only) +- **Persistence:** electron-store + safeStorage (credentials) ## Commands @@ -27,13 +28,106 @@ npm run build:linux # build + electron-builder --linux ## Architecture ``` -Electron main (src/main/index.ts) - ├── Dev: loads renderer dev server (Vite HMR) - └── Prod: loads out/renderer/index.html - └── Vue 3 SPA (src/renderer/) - @renderer alias → src/renderer/src/ +Electron main (src/main/) + ├── index.ts # Window creation, app lifecycle + ├── redis-service.ts # ioredis wrapper (connect, scan, CRUD, stream) + ├── store.ts # electron-store (connections, settings) + ├── credential.ts # safeStorage encrypt/decrypt + ├── win-state.ts # window position persistence + └── ipc-handlers.ts # all IPC channel handlers + +Preload (src/preload/) + ├── index.ts # contextBridge.exposeInMainWorld + └── index.d.ts # ElectronAPI type declarations + +Renderer (src/renderer/src/) + ├── main.ts # Vue 3 bootstrap (Pinia, Element Plus) + ├── App.vue # Shell layout (TitleBar + Sidebar + MainArea + StatusBar) + ├── 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 + ├── i18n/ + │ ├── index.ts # useI18n composable + │ └── locales/ + │ ├── en.ts # English + │ └── zh-CN.ts # 中文 + └── composables/ + └── useKeyboard.ts # keyboard shortcut handler ``` +## IPC Channels + +| Channel | Type | Purpose | +|---------|------|---------| +| `redis:connect` | invoke | Create Redis connection | +| `redis:disconnect` | invoke | Close connection | +| `redis:execute` | invoke | Execute arbitrary command | +| `redis:ping` | invoke | Health check ping | +| `redis:isConnected` | invoke | Check connection status | +| `redis:scanKeys` | invoke | SCAN with pattern | +| `redis:getString` | invoke | GET string value | +| `redis:setString` | invoke | SET string value | +| `redis:hashScan` | invoke | HSCAN fields | +| `redis:hashSet` | invoke | HSET field | +| `redis:hashDel` | invoke | HDEL field | +| `redis:listRange` | invoke | LRANGE elements | +| `redis:listPush` | invoke | RPUSH elements | +| `redis:setMembers` | invoke | SMEMBERS | +| `redis:zsetRange` | invoke | ZRANGE with scores | +| `redis:streamRange` | invoke | XRANGE entries | +| `redis:streamAdd` | invoke | XADD entry | +| `redis:batchDelete` | invoke | Pipeline DEL multiple keys | +| `redis:renameKey` | invoke | RENAME key | +| `redis:setTTL` | invoke | EXPIRE/PERSIST | +| `redis:selectDb` | invoke | SELECT database | +| `redis:dbSize` | invoke | DBSIZE | +| `redis:slowLogGet` | invoke | SLOWLOG GET | +| `redis:memoryUsage` | invoke | MEMORY USAGE | +| `storage:getConnections` | invoke | Read connections | +| `storage:saveConnection` | invoke | Save connection | +| `storage:deleteConnection` | invoke | Delete connection | +| `credential:encrypt` | invoke | safeStorage encrypt | +| `credential:decrypt` | invoke | safeStorage decrypt | +| `dialog:openFile` | invoke | Open file picker | +| `theme:get` | invoke | Get OS dark mode | +| `theme:set` | send | Set theme source | +| `window:minimize` | send | Minimize window | +| `window:maximize` | send | Toggle maximize | +| `window:close` | send | Close window | + +## Keyboard Shortcuts + +| Shortcut | Action | Scope | +|----------|--------|-------| +| `Ctrl+N` | New connection | Global | +| `Ctrl+R` | Refresh keys | Global | +| `F5` | Refresh keys | Global | +| `Delete` | Delete selected key | Global | +| `Escape` | Deselect key | Global | + ## Build config - `electron.vite.config.ts` defines three build targets: main, preload, renderer @@ -47,16 +141,12 @@ Electron main (src/main/index.ts) - Web target includes `src/renderer/**/*` - `@renderer` alias resolves to `src/renderer/src` -## Source layout (expected) +## Security -``` -src/ -├── main/ # Electron main process -├── preload/ # Preload scripts -└── renderer/ # Vue 3 app - ├── index.html - └── src/ -``` +- `contextIsolation: true` — renderer has zero Node.js access +- `nodeIntegration: false` — no Node globals in renderer +- `safeStorage` — OS-level encryption for credentials +- All Redis operations go through typed IPC to main process ## Legacy diff --git a/README.md b/README.md index 17540fc..d9bcfed 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,61 @@ A modern Redis desktop manager built with Electron + Vue 3 + Vite. -> Fork of [AnotherRedisDesktopManager](https://github.com/qishibo/AnotherRedisDesktopManager). +> Fork of [AnotherRedisDesktopManager](https://github.com/qishibo/AnotherRedisDesktopManager). > The legacy Vue 2 codebase is archived in [`legacy/`](legacy/). +## Features + +### Connection Management +- Create, edit, delete connections with host/port/password +- TLS/SSL support +- **Test connection** before saving +- **Import/Export** connections as JSON +- Health check with auto-reconnect indicator + +### Key Browser +- **Pattern search** with Redis MATCH syntax (e.g. `user:*`, `cache:??`) +- Local filter for quick search +- SCAN-based pagination +- Tree view with key separator +- Multi-select for batch operations +- Batch delete with pipeline + +### Type Editors +- **String** - view/edit with auto JSON formatting +- **Hash** - field table with add/edit/delete +- **List** - paginated view with push/edit/remove +- **Set** - member list with filter, add/remove +- **Zset** - sorted set with score, add/remove +- **Stream** - entry viewer with field management + +### Key Operations +- **TTL** - view and edit expiration +- **Rename** - rename keys with existence check +- **Copy key name** to clipboard +- Delete single or batch + +### Analysis Tools +- **Redis CLI** - interactive terminal with command history +- **Slow Log** - view slow commands with timing +- **INFO dashboard** - server statistics +- **DB selector** - switch between databases 0-15 + +### Settings +- **Theme** - dark, light, or system +- **Language** - English / 中文 +- **SCAN count** - keys per scan iteration +- **Font size** - adjustable + +### Keyboard Shortcuts +| Shortcut | Action | +|----------|--------| +| `Ctrl+N` | New connection | +| `Ctrl+R` | Refresh keys | +| `F5` | Refresh keys | +| `Delete` | Delete selected key | +| `Escape` | Deselect key | + ## Dev ```bash @@ -24,6 +76,27 @@ npm run build:win ## Stack - **Shell:** Electron 33 -- **Renderer:** Vue 3 + Element Plus + Vue Router -- **Build:** electron-vite + Vite 6 + TypeScript +- **Preload:** contextBridge + typed IPC +- **Renderer:** Vue 3 + Pinia + Element Plus +- **Build:** electron-vite + Vite 6 + TypeScript 5 - **Redis client:** ioredis 5 +- **Persistence:** electron-store + safeStorage + +## Architecture + +``` +Electron main (src/main/) + ├── RedisService (ioredis wrapper) + ├── electron-store (persistence) + ├── safeStorage (credential encryption) + └── IPC handlers (typed channels) + +Preload (src/preload/) + └── contextBridge → window.electronAPI + +Renderer (src/renderer/src/) + ├── stores/ (Pinia: connection, key, app) + ├── components/ (Vue 3 SFCs) + ├── i18n/ (English + Chinese) + └── composables/ (useKeyboard) +```