|
| 1 | +--- |
| 2 | +status: planned |
| 3 | +created: 2026-01-06 |
| 4 | +priority: medium |
| 5 | +tags: |
| 6 | +- ui-vite |
| 7 | +- refactoring |
| 8 | +- architecture |
| 9 | +- tech-debt |
| 10 | +- api |
| 11 | +depends_on: |
| 12 | +- 193-frontend-ui-parity |
| 13 | +- 198-ui-vite-remaining-issues |
| 14 | +created_at: 2026-01-06T15:10:01.548099Z |
| 15 | +updated_at: 2026-01-06T15:10:35.720936Z |
| 16 | +--- |
| 17 | + |
| 18 | +# UI-Vite Backend Adapter Migration |
| 19 | + |
| 20 | +> **Status**: 🗓️ Planned · **Created**: 2026-01-06 · **Priority**: Medium · **Tags**: ui-vite, refactoring, architecture, tech-debt, api |
| 21 | +
|
| 22 | +## Overview |
| 23 | + |
| 24 | +**Problem**: @leanspec/ui-vite has **duplicate API implementations** - `api.ts` (actively used) and `backend-adapter.ts` (created but unused). This creates maintenance burden, code duplication, and missed opportunity for desktop/Tauri support. |
| 25 | + |
| 26 | +**Current State**: |
| 27 | +- All components import from `api.ts` directly (18 files) |
| 28 | +- `backend-adapter.ts` exists with `HttpBackendAdapter` + `TauriBackendAdapter` abstraction |
| 29 | +- Both files have ~200 lines of duplicate HTTP methods |
| 30 | +- Bug fixes must be applied twice (e.g., recent PATCH `/api/specs/:spec/metadata` endpoint fix) |
| 31 | + |
| 32 | +**Goal**: Consolidate on `backend-adapter.ts` as the single API abstraction layer, delete duplicate code from `api.ts`, and enable future Tauri desktop support. |
| 33 | + |
| 34 | +**Why Now**: Just fixed a bug (405 Method Not Allowed) that required updating both files. This tech debt will cause more issues as the API evolves. |
| 35 | + |
| 36 | +## Design |
| 37 | + |
| 38 | +### Architecture Decision |
| 39 | + |
| 40 | +**Keep**: `backend-adapter.ts` (abstracts HTTP vs Tauri) |
| 41 | +**Delete**: Duplicate methods in `api.ts` (keep only adapters/utilities) |
| 42 | + |
| 43 | +**Rationale**: |
| 44 | +1. `backend-adapter.ts` already has Tauri support infrastructure (needed for desktop app) |
| 45 | +2. Interface-based design enables testing and mocking |
| 46 | +3. Cleaner separation of concerns (adapter pattern) |
| 47 | +4. Future-proof for multi-platform distribution |
| 48 | + |
| 49 | +### Current File Structure |
| 50 | + |
| 51 | +**api.ts** (~380 lines): |
| 52 | +```typescript |
| 53 | +// ✅ Keep these utilities |
| 54 | +- adaptSpec(), adaptSpecDetail(), adaptStats() |
| 55 | +- adaptProject(), normalizeProjectsResponse() |
| 56 | +- extractSpecNumber(), estimateTokenCount() |
| 57 | +- Type exports |
| 58 | + |
| 59 | +// ❌ Delete these (duplicate of backend-adapter) |
| 60 | +- api.getSpecs() |
| 61 | +- api.getSpec() |
| 62 | +- api.updateSpec() |
| 63 | +- api.getProjects() |
| 64 | +- ... 15+ more methods (~200 lines of duplication) |
| 65 | +``` |
| 66 | + |
| 67 | +**backend-adapter.ts** (~241 lines): |
| 68 | +```typescript |
| 69 | +// ✅ Keep entire file |
| 70 | +- BackendAdapter interface |
| 71 | +- HttpBackendAdapter class |
| 72 | +- TauriBackendAdapter class |
| 73 | +- getBackend() factory |
| 74 | +``` |
| 75 | + |
| 76 | +### Migration Strategy |
| 77 | + |
| 78 | +**Phase 1: Extend Backend Adapter** |
| 79 | + |
| 80 | +Add missing methods to `backend-adapter.ts` that exist in `api.ts`: |
| 81 | +- `createProject()` |
| 82 | +- `updateProject()` |
| 83 | +- `deleteProject()` |
| 84 | +- `validateProject()` |
| 85 | +- `getContextFiles()` |
| 86 | +- `getContextFile()` |
| 87 | +- `listDirectory()` |
| 88 | +- `searchSpecs()` |
| 89 | + |
| 90 | +**Phase 2: Update api.ts** |
| 91 | + |
| 92 | +Remove duplicate implementations and re-export from backend adapter: |
| 93 | + |
| 94 | +```typescript |
| 95 | +// api.ts (after refactor) |
| 96 | +import { getBackend } from './backend-adapter'; |
| 97 | +export { getBackend } from './backend-adapter'; |
| 98 | + |
| 99 | +// Keep utilities |
| 100 | +export { |
| 101 | + adaptSpec, |
| 102 | + adaptSpecDetail, |
| 103 | + adaptStats, |
| 104 | + adaptProject, |
| 105 | + normalizeProjectsResponse, |
| 106 | + extractSpecNumber, |
| 107 | + estimateTokenCount, |
| 108 | + // ... other utilities |
| 109 | +}; |
| 110 | + |
| 111 | +// Delegate to backend adapter (zero breaking changes) |
| 112 | +export const api = getBackend(); |
| 113 | +``` |
| 114 | + |
| 115 | +**Phase 3: Verification** |
| 116 | + |
| 117 | +Test all 18 importing files still work with **zero breaking changes**. |
| 118 | + |
| 119 | +## Plan |
| 120 | + |
| 121 | +- [x] Identify duplication - Mapped all duplicate methods |
| 122 | +- [ ] Port missing methods to `BackendAdapter` interface |
| 123 | +- [ ] Implement missing methods in `HttpBackendAdapter` |
| 124 | +- [ ] Add stub implementations in `TauriBackendAdapter` (for future) |
| 125 | +- [ ] Update `api.ts` to remove duplicates and re-export backend adapter |
| 126 | +- [ ] Run type checks (`pnpm -C packages/ui-vite typecheck`) |
| 127 | +- [ ] Test all pages manually (dashboard, specs, stats, dependencies, projects, settings) |
| 128 | +- [ ] Update unit tests if needed (`api.test.ts`) |
| 129 | +- [ ] Document the pattern with JSDoc comments |
| 130 | +- [ ] Verify production build works (`pnpm -C packages/ui-vite build`) |
| 131 | + |
| 132 | +## Test |
| 133 | + |
| 134 | +**Type Safety**: |
| 135 | +- [ ] `pnpm -C packages/ui-vite typecheck` passes with no errors |
| 136 | +- [ ] No missing exports or broken imports in any component |
| 137 | + |
| 138 | +**Runtime Verification** (test with `pnpm -C packages/ui-vite dev`): |
| 139 | +- [ ] Dashboard page loads and displays specs |
| 140 | +- [ ] Spec detail page fetches and renders content |
| 141 | +- [ ] Status/priority updates work (PATCH `/api/specs/:spec/metadata`) |
| 142 | +- [ ] Projects page lists all projects |
| 143 | +- [ ] Stats page displays metrics and charts |
| 144 | +- [ ] Search functionality works |
| 145 | +- [ ] Dependencies graph renders correctly |
| 146 | +- [ ] Context files page works |
| 147 | +- [ ] Settings page loads |
| 148 | + |
| 149 | +**Unit Tests**: |
| 150 | +- [ ] `pnpm -C packages/ui-vite test` passes all tests |
| 151 | +- [ ] Mock/stub patterns in `api.test.ts` still work |
| 152 | +- [ ] No test failures related to API imports |
| 153 | + |
| 154 | +**Build Verification**: |
| 155 | +- [ ] `pnpm -C packages/ui-vite build` succeeds |
| 156 | +- [ ] Production bundle size doesn't increase significantly |
| 157 | + |
| 158 | +## Notes |
| 159 | + |
| 160 | +### Files That Import api.ts (18 total) |
| 161 | + |
| 162 | +**Pages** (6 files): |
| 163 | +- `src/pages/StatsPage.tsx` |
| 164 | +- `src/pages/SpecsPage.tsx` |
| 165 | +- `src/pages/ProjectsPage.tsx` |
| 166 | +- `src/pages/DependenciesPage.tsx` |
| 167 | +- `src/pages/SettingsPage.tsx` |
| 168 | +- `src/pages/DashboardPage.tsx` |
| 169 | + |
| 170 | +**Components** (6 files): |
| 171 | +- `src/components/SpecsNavSidebar.tsx` |
| 172 | +- `src/components/QuickSearch.tsx` |
| 173 | +- `src/components/metadata-editors/StatusEditor.tsx` |
| 174 | +- `src/components/metadata-editors/TagsEditor.tsx` |
| 175 | +- `src/components/metadata-editors/PriorityEditor.tsx` |
| 176 | +- `src/components/projects/DirectoryPicker.tsx` |
| 177 | + |
| 178 | +**Tests** (1 file): |
| 179 | +- `src/lib/api.test.ts` |
| 180 | + |
| 181 | +**Type-only imports** (5 files): |
| 182 | +- `src/components/specs/ListView.tsx` |
| 183 | +- `src/components/specs/BoardView.tsx` |
| 184 | +- `src/components/dashboard/SpecListItem.tsx` |
| 185 | +- `src/components/spec-detail/EditableMetadata.tsx` |
| 186 | +- `src/components/dashboard/DashboardClient.tsx` |
| 187 | + |
| 188 | +All should continue working with re-export pattern (zero breaking changes). |
| 189 | + |
| 190 | +### Backend Adapter Methods |
| 191 | + |
| 192 | +**Already implemented in `backend-adapter.ts`**: |
| 193 | +- ✅ `getProjects()` |
| 194 | +- ✅ `switchProject()` |
| 195 | +- ✅ `getSpecs()` |
| 196 | +- ✅ `getSpec()` |
| 197 | +- ✅ `updateSpec()` |
| 198 | +- ✅ `getStats()` |
| 199 | +- ✅ `getProjectStats()` |
| 200 | +- ✅ `getDependencies()` |
| 201 | + |
| 202 | +**Need to add to backend-adapter** (8 methods): |
| 203 | +- ❌ `createProject(path, options)` |
| 204 | +- ❌ `updateProject(projectId, updates)` |
| 205 | +- ❌ `deleteProject(projectId)` |
| 206 | +- ❌ `validateProject(projectId)` |
| 207 | +- ❌ `getContextFiles()` |
| 208 | +- ❌ `getContextFile(path)` |
| 209 | +- ❌ `listDirectory(path)` |
| 210 | +- ❌ `searchSpecs(query, filters)` |
| 211 | + |
| 212 | +### Why backend-adapter.ts Was Created |
| 213 | + |
| 214 | +From git history (commit ec949bd): |
| 215 | +> "Backend adapter pattern for web (HTTP) vs desktop (Tauri IPC) - This allows the same UI code to work in both browser and Tauri contexts" |
| 216 | +
|
| 217 | +The abstraction was designed for **dual-environment support**: |
| 218 | +- **Web**: Uses `HttpBackendAdapter` with `fetch()` calls to Rust HTTP server |
| 219 | +- **Desktop**: Uses `TauriBackendAdapter` with Tauri IPC commands (future) |
| 220 | + |
| 221 | +However, the migration was **never completed** - components continued importing from `api.ts` directly. |
| 222 | + |
| 223 | +### Related Specs |
| 224 | + |
| 225 | +**Depends on**: |
| 226 | +- 193-frontend-ui-parity (need stable API before refactoring) |
| 227 | +- 198-ui-vite-remaining-issues (fix existing bugs first) |
| 228 | + |
| 229 | +**Enables**: |
| 230 | +- 202-ui-vite-type-system-consolidation (eliminate adapter overhead) |
| 231 | +- Future Tauri desktop integration |
| 232 | +- Easier testing and mocking |
| 233 | +- Single source of truth for API methods |
| 234 | + |
| 235 | +**Part of**: UI-Vite tech debt cleanup and architectural improvements |
0 commit comments