Conversation
|
There was a problem hiding this comment.
Pull Request Overview
This PR migrates core functionality and components to TypeScript, introduces a “Quick Scan” feature for both AppData and Developer cleaners, and centralizes utility logic and testing infrastructure.
- Added separate Vitest config for main-process tests and updated
package.jsonscripts for testing and packaging. - Converted renderer and main process codebases to TypeScript, harmonized props/emits definitions, and unified size/date formatting.
- Introduced Quick Scan panels, persistence via
fileUtils, and comprehensive tests for utilities, workers, and CLI workflows.
Reviewed Changes
Copilot reviewed 49 out of 55 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| vitest.main.config.ts | Add main-process Vitest configuration |
| vite.config.ts | Update Vite config to include tests and TS support |
| vite.config.js | Remove legacy JS config |
| sonar-project.properties | Update Sonar coverage and exclusion paths |
| package.json | Bump version, update scripts and dependencies |
| src/types/developer-cleaner.ts | Define shared Worker message/response interfaces |
| src/renderer/utils/formatters.ts | New size/date formatting helpers |
| src/renderer/utils/categoryColors.ts | Centralize cache-category color mapping |
| src/renderer/utils/tests/formatters.test.ts | Tests for formatting utilities |
| src/renderer/utils/tests/categoryColors.test.ts | Tests for color mapping |
| src/renderer/tsconfig.json | Renderer TS config for strict type checking |
| src/renderer/index.html | Update module entry to .ts |
| src/renderer/components/**/*.vue | Migrate Vue components to TS, unify emits/props |
| src/main/tsconfig.json | Main-process TS config for strict type checking |
| src/main/preload.ts | Convert preload API to TS and extend methods |
| src/main/main.ts | Convert main entry to TS, improve IPC and workers |
| src/main/fileUtils.ts | New file-based persistence utilities |
| src/main/developerScanWorker.ts | Convert dev-scan worker to TS, add glob utilities |
| src/main/appDataScanWorker.ts | Convert AppData scan worker to TS, batch messaging |
| src/main/appDataCleaner.ts | Add TS-based AppData path discovery and deletion |
| src/main/tests/fileUtils.test.ts | Tests for fileUtils persistence methods |
| src/main/tests/**/*.test.ts | Tests for directory sizing and worker logic |
| .github/workflows/*.yml | Update CI workflows for new branches and artifacts |
Comments suppressed due to low confidence (1)
src/main/developerScanWorker.ts:150
- The single-asterisk glob handler lacks unit tests. Adding tests for
handleSingleAsteriskPattern(and related literal patterns) will help ensure glob expansions behave as expected.
await searchGlobPattern(subPath, patternParts, partIndex + 1, results);
|
|
||
| // Save projects after successful scan | ||
| // Convert reactive objects to plain objects to avoid cloning issues | ||
| const plainProjects: ProjectInfo[] = projects.value.map(project => ({ |
There was a problem hiding this comment.
Saving plainProjects with caches: [] discards the discovered cache details, which will break quick-scan reload. Include the actual caches array so that cached data is persisted correctly.
| ipcMain.handle("stop-developer-scan", () => { | ||
| if (currentDeveloperScanWorker) { | ||
| currentDeveloperScanWorker.terminate(); | ||
| currentDeveloperScanWorker = null; | ||
| currentDeveloperScanWorker.postMessage({ type: "stop" }); |
There was a problem hiding this comment.
After signaling the worker to stop, the thread remains alive. Consider calling currentDeveloperScanWorker.terminate() once it acknowledges the stop to avoid resource leaks.
| // Calculate directory size recursively | ||
| export async function getDirSize(dirPath: string): Promise<number> { | ||
| let size = 0; | ||
| try { | ||
| const entries = await fs.readdir(dirPath, { withFileTypes: true }); | ||
|
|
||
| for (const entry of entries) { | ||
| const fullPath = path.join(dirPath, entry.name); | ||
|
|
||
| if (entry.isDirectory()) { | ||
| size += await getDirSize(fullPath); | ||
| } else { | ||
| try { | ||
| const stats = await fs.stat(fullPath); | ||
| size += stats.size; | ||
| } catch (err) { | ||
| console.warn("Error getting file size:", err); | ||
| } | ||
| } | ||
| } | ||
| } catch (err) { | ||
| console.warn("Error getting directory size:", err); |
There was a problem hiding this comment.
[nitpick] This recursive implementation may cause stack overflows or slowdowns on very deep directory trees. Consider using an iterative traversal or streaming API to improve performance and avoid deep recursion.
| // Calculate directory size recursively | |
| export async function getDirSize(dirPath: string): Promise<number> { | |
| let size = 0; | |
| try { | |
| const entries = await fs.readdir(dirPath, { withFileTypes: true }); | |
| for (const entry of entries) { | |
| const fullPath = path.join(dirPath, entry.name); | |
| if (entry.isDirectory()) { | |
| size += await getDirSize(fullPath); | |
| } else { | |
| try { | |
| const stats = await fs.stat(fullPath); | |
| size += stats.size; | |
| } catch (err) { | |
| console.warn("Error getting file size:", err); | |
| } | |
| } | |
| } | |
| } catch (err) { | |
| console.warn("Error getting directory size:", err); | |
| // Calculate directory size iteratively | |
| export async function getDirSize(dirPath: string): Promise<number> { | |
| let size = 0; | |
| const stack = [dirPath]; | |
| while (stack.length > 0) { | |
| const currentPath = stack.pop(); | |
| try { | |
| const entries = await fs.readdir(currentPath, { withFileTypes: true }); | |
| for (const entry of entries) { | |
| const fullPath = path.join(currentPath, entry.name); | |
| if (entry.isDirectory()) { | |
| stack.push(fullPath); | |
| } else { | |
| try { | |
| const stats = await fs.stat(fullPath); | |
| size += stats.size; | |
| } catch (err) { | |
| console.warn("Error getting file size:", err); | |
| } | |
| } | |
| } | |
| } catch (err) { | |
| console.warn("Error getting directory size:", err); | |
| } |
| try { | ||
| const contents = await window.electronAPI.getFolderContents(props.folderPath) | ||
| treeData.value = contents.map(item => ({ | ||
| treeData.value = contents.map((item: any) => ({ |
There was a problem hiding this comment.
Using any for item forfeits type safety. Replace with the correct FolderItem type (or a custom interface) to catch errors at compile time.
| treeData.value = contents.map((item: any) => ({ | |
| treeData.value = contents.map((item: FolderItem) => ({ |



No description provided.