7e5d61c099
- Electron 33 main process with frameless window, IPC, win-state persistence - Preload with contextBridge typed API (window, theme, dialog) - Vue 3 + Pinia + Element Plus + Vue Router renderer - Dark/light dual theme via CSS custom properties - TitleBar with window controls + theme toggle - StatusBar placeholder - Design spec document
9.5 KiB
9.5 KiB
JRedisDesktop v2 — Design Spec
Date: 2026-07-04 Status: Approved
1. Project Identity
Fork of AnotherRedisDesktopManager. Full rewrite of the legacy Vue 2 + Webpack 4 + Electron 12 codebase (archived in legacy/) to Electron 33 + Vue 3 + Vite 6 + TypeScript 5.
2. Scope & Phasing
Phase 1: Architecture Skeleton (Week 1-2)
- Electron main process with contextIsolation + preload + contextBridge
- Vue 3 SPA with Vue Router + Element Plus + Pinia
- electron-vite three-target build pipeline (main/preload/renderer)
- Dark/light dual theme system via CSS variables
- Window management (min/max/close, win-state persistence)
Phase 2: Connection Management MVP (Week 2-3)
- Standalone Redis connections (host:port + password/ACL)
- TLS support (CA/cert/key file reading via main process)
- Connection list CRUD with drag-to-reorder
- Secure credential storage (electron-store + safeStorage encryption)
- SSH tunnel support (single node)
Phase 3: Key Browser MVP (Week 3-4)
- Key list with SCAN-based pagination + tree view (key separator)
- String viewer/editor (plain text, JSON formatting)
- Hash viewer/editor (field table, pagination, add/edit/delete)
- Server INFO status dashboard
- Database switching
Phase 4: Advanced Features (Iterative)
- List/Set/Zset/Stream editors
- Format viewers (Msgpack, Protobuf, Pickle, Brotli, Gzip, etc.)
- Redis CLI terminal
- Cluster/Sentinel connections
- Slow log, memory analysis, batch delete
- i18n (13 languages from legacy)
- Monaco JSON editor
- Custom shell formatters
3. Architecture
Process Model
┌─────────────────────────────────────────────┐
│ Main Process │
│ ├── Window management │
│ ├── RedisService (ioredis + SSH + TLS) │
│ ├── electron-store (persistence) │
│ ├── safeStorage (credential encryption) │
│ └── IPC handlers (typed channels) │
├─────────────────────────────────────────────┤
│ Preload (contextBridge) │
│ └── window.electronAPI (typed IPC methods) │
├─────────────────────────────────────────────┤
│ Renderer (Vue 3 SPA) │
│ ├── Pinia stores (connection, key, app) │
│ ├── Vue Router │
│ ├── Element Plus │
│ └── Composition API components │
└─────────────────────────────────────────────┘
Key Architectural Decision: RedisService in Main Process
ioredis depends on Node net/tls modules and cannot run in a contextIsolation renderer. All Redis operations go through typed IPC:
Renderer (Pinia action) → IPC invoke → Main (RedisService) → ioredis → Redis
IPC latency (~1ms) is negligible vs Redis network latency (1-100ms). High-frequency operations (SCAN) use batch IPC to minimize round trips.
Renderer Component Tree (MVP)
App.vue
├── TitleBar.vue (window controls, connection badge)
├── Sidebar.vue
│ ├── ConnectionSearch.vue (filter connections)
│ ├── ConnectionList.vue (card list, drag sort)
│ │ └── ConnectionCard.vue
│ └── NewConnectionBtn.vue
├── MainArea.vue (tab host)
│ ├── StatusView.vue (INFO dashboard with stat cards)
│ ├── KeyBrowser.vue (key list + tree + detail)
│ │ ├── KeyList.vue (SCAN pagination, tree toggle)
│ │ └── KeyDetail.vue (type dispatcher)
│ │ ├── StringEditor.vue
│ │ └── HashEditor.vue
│ └── CliView.vue (Phase 4)
└── StatusBar.vue (connection status, latency)
Pinia Stores
| Store | Responsibility |
|---|---|
useConnectionStore |
Connections CRUD, active connection, RedisService proxy |
useKeyStore |
Key list, tree view, selected key, key data cache |
useAppStore |
Theme (dark/light), settings, i18n locale, UI state |
IPC Channel Design
| Channel | Type | Direction | Purpose |
|---|---|---|---|
redis:connect |
invoke | renderer→main | Create Redis connection, return client ID |
redis:disconnect |
invoke | renderer→main | Close connection by ID |
redis:execute |
invoke | renderer→main | Execute Redis command, return result |
redis:event |
on | main→renderer | Connection events (ready, error, close) |
storage:get |
invoke | renderer→main | Read from electron-store |
storage:set |
invoke | renderer→main | Write to electron-store |
credential:encrypt |
invoke | renderer→main | Encrypt via safeStorage |
credential:decrypt |
invoke | renderer→main | Decrypt via safeStorage |
dialog:openFile |
invoke | renderer→main | Open file picker, return file content |
window:minimize |
send | renderer→main | Minimize window |
window:maximize |
send | renderer→main | Toggle maximize |
window:close |
send | renderer→main | Close window |
theme:set |
send | renderer→main | Set nativeTheme source |
theme:os-updated |
on | main→renderer | OS theme change notification |
4. UI Design
Visual Style
- Dark theme: Deep blue-black gradient background, perspective cards with rotateY/X micro-angles, ambient light overlays, glow dot status indicators, multi-tier shadows for depth hierarchy
- Light theme: Clean white background, soft shadows, purple-blue accent, light frosted glass effects
- Dual theme: CSS custom properties (
--bg,--text,--border,--accent,--shadow) switch at root level. Follows OS preference by default, manual toggle persisted.
Layout
- Left sidebar (~260px): connection cards with search + new connection button
- Right main area: stat cards row + tab bar + content panel
- Bottom status bar: connection status + latency + app version
- Resizable sidebar (drag handle)
5. Data Persistence
Strategy: Mixed
- electron-store (main process): Non-sensitive data — connection list, settings, UI preferences
- safeStorage (main process): Sensitive data — passwords, SSH private keys, TLS certs
Data Shape
// electron-store schema
interface AppStorage {
connections: Connection[];
settings: AppSettings;
windowState: { x: number; y: number; width: number; height: number; maximized: boolean };
}
interface Connection {
id: string;
name: string;
host: string;
port: number;
auth: string; // encrypted via safeStorage
username: string; // ACL username
tls: boolean;
tlsCaPath: string;
tlsCertPath: string;
tlsKeyPath: string;
sshEnabled: boolean;
sshHost: string;
sshPort: number;
sshUsername: string;
sshPassword: string; // encrypted via safeStorage
sshPrivateKeyPath: string;
cluster: boolean;
sentinelMasterName: string;
separator: string; // key tree separator, default ":"
order: number;
createdAt: number;
}
interface AppSettings {
theme: 'system' | 'dark' | 'light';
locale: string;
fontSize: number;
scanCount: number; // keys per SCAN page
// ... more settings as needed
}
6. Security Model
- contextIsolation: true — renderer has zero Node.js/Electron API access
- nodeIntegration: false — no Node globals in renderer
- contextBridge — only typed API surface exposed via
window.electronAPI - safeStorage — OS-level encryption for credentials (DPAPI on Windows, Keychain on macOS, libsecret on Linux)
- IPC validation — all IPC handlers validate input before executing
- No remote module — all main-process features accessed via IPC
7. Compatibility Mitigations
| Legacy Pattern | v2 Approach |
|---|---|
redisClient.js in renderer |
RedisService in main, typed IPC proxy |
fs.readFileSync for TLS |
dialog:openFile IPC → main reads file |
remote.app sandbox bookmarks |
Main process handles file access |
vue.$bus / vue.$message |
mitt EventEmitter + ElMessage composable |
Vue.prototype.$storage |
useConnectionStore() composable |
Vue.prototype.$util |
Pure functions in utils/ |
Node zlib for decompression |
Web DecompressionStream + WASM fallback |
child_process.exec formatters |
IPC → main process spawn (Phase 4) |
window.localStorage |
electron-store IPC |
| Monaco + webpack plugin | ESM Monaco + vite plugin (Phase 4) |
8. Build & Dev
npm run dev # electron-vite dev (HMR, renderer on :5173)
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
npm run build:mac # build + electron-builder --mac
npm run build:linux # build + electron-builder --linux
9. Dependencies
Runtime
ioredis^5.7.0 — Redis client (main process)tunnel-ssh^5.x — SSH tunneling (main process)electron-store^10.x — persistence (main process)
Dev / Renderer
electron^33.4.0electron-vite^3.0.0vue^3.5.0vue-router^4.5.0pinia^2.xelement-plus^2.9.0typescript^5.7.0vite^6.0.0electron-builder^25.1.0