chore(desktop): bump version to 0.0.34#482
Conversation
- Add @superset/local-db package with Drizzle ORM schema - Migrate all database operations from lowdb (db.json) to SQLite - Add better-sqlite3 native module support for Electron - Update all routers to use Drizzle queries - Remove lowdb dependency - Add UUID defaults for all ID fields (prep for local-first) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove workspaces.test.ts that was testing mock behavior rather than real logic (tests were mocking Drizzle's complex query API) - Fix formatting in local-db/index.ts - The git parsing logic these tests covered should be tested via integration tests or by extracting pure functions 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add more electron exports to test mock (clipboard, screen, Notification, Menu) to prevent intermittent test failures from unresolved imports. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add lowdb ^7.0.1 back to desktop dependencies (app-state still uses it) - Add crypto import from node:crypto in local-db schema.ts 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace crypto.randomUUID() with uuid v4 to avoid node:crypto module resolution issues in CI environments. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
Warning Rate limit exceeded@saddlepaddle has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 6 minutes and 4 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (2)
WalkthroughThis PR migrates the desktop application's data persistence layer from lowdb (in-memory JSON) to SQLite with Drizzle ORM. It introduces a new Changes
Sequence DiagramsequenceDiagram
actor App as Electron App
participant Init as Startup (main/index.ts)
participant LocalDB as LocalDb<br/>(Drizzle + SQLite)
participant SQLite as SQLite<br/>Database
participant LegacyDB as Legacy<br/>db.json
App->>Init: Start application
Init->>LocalDB: import localDb
rect rgb(200, 220, 255)
Note over LocalDB,SQLite: Database Initialization
LocalDB->>LocalDB: Resolve migrations dir<br/>(prod/dev/test layouts)
LocalDB->>SQLite: Execute schema migrations<br/>(0000_initial_schema.sql)
LocalDB->>LocalDB: Check for legacy db.json
end
alt Legacy data exists AND SQLite empty
rect rgb(255, 230, 200)
Note over LocalDB,LegacyDB: One-time Data Migration
LocalDB->>LegacyDB: Read legacy JSON<br/>(projects, workspaces, etc.)
LocalDB->>SQLite: INSERT projects, worktrees,<br/>workspaces, settings
LocalDB->>LocalDB: Deduplicate workspaces<br/>& reconstruct branches
LocalDB->>LegacyDB: Backup db.json
LocalDB->>LocalDB: Log migration success
end
else No migration needed
LocalDB->>LocalDB: Continue with existing DB
end
Init->>LocalDB: console.log(localDb ready)
App->>App: Routers now use localDb<br/>for all CRUD operations
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
🚀 Preview Deployment🔗 Preview Links
Preview updates automatically with new commits |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (9)
apps/desktop/src/lib/trpc/routers/external/index.ts (1)
58-65: Consider error handling for database operations.The database upsert operation has no error handling. While tRPC will catch and wrap any thrown errors, synchronous database failures (e.g., disk full, permission issues) will result in generic 500 errors without helpful context.
🔎 Add try/catch for better error messages
.mutation(async ({ input }) => { + try { localDb .insert(settings) .values({ id: 1, lastUsedApp: input.app }) .onConflictDoUpdate({ target: settings.id, set: { lastUsedApp: input.app }, }) .run(); + } catch (error) { + console.error('[external] Failed to save lastUsedApp:', error); + throw new Error('Failed to save application preference'); + } await openPathInApp(input.path, input.app); }),apps/desktop/src/lib/trpc/routers/workspaces/utils/worktree.ts (2)
8-15: Consider adding error handling for database queries.The
getWorktreePathfunction has no error handling. Database errors (e.g., connection issues, corruption) will throw and potentially crash the main process.🔎 Add defensive error handling
export function getWorktreePath(worktreeId: string): string | undefined { + try { const worktree = localDb .select() .from(worktrees) .where(eq(worktrees.id, worktreeId)) .get(); return worktree?.path; + } catch (error) { + console.error('[worktree] Failed to get worktree path:', error); + return undefined; + } }
8-15: Inconsistent return types for "not found" cases.
getWorktreePathreturnsstring | undefinedwhilegetWorkspacePathreturnsstring | null. For consistency and clarity, both should use the same convention for representing "not found."Consider standardizing on
nullfor "not found" across both functions, or document the rationale for the difference.Also applies to: 22-43
apps/desktop/src/main/lib/local-db/index.ts (2)
27-70: Complex path resolution logic may be fragile.The
getMigrationsDirectory()function has multiple fallback paths with environment-specific logic. This complexity increases the risk of misconfiguration in different deployment scenarios.Consider:
- Adding debug logging for the resolved path to aid troubleshooting
- Testing each branch (packaged, dev, preview, test) explicitly
- Failing fast with a clear error if migrations aren't found, rather than silently falling back
🔎 Add debug logging
function getMigrationsDirectory(): string { + const logPath = (source: string, path: string) => { + console.log(`[local-db] Migrations path (${source}): ${path}`); + return path; + }; + // Check if running in Electron (app.getAppPath exists) const isElectron = typeof app?.getAppPath === "function" && typeof app?.isPackaged === "boolean"; if (isElectron && app.isPackaged) { - return join(process.resourcesPath, "resources/migrations"); + return logPath("packaged", join(process.resourcesPath, "resources/migrations")); } // ... add logging to other branches
216-216: Consider async initialization pattern for database.The legacy migration runs synchronously at module load time, blocking the main process startup. For large databases, this could cause noticeable delays. Consider moving database initialization to an async function called during app startup with a loading indicator.
This is not critical for the current PR but could improve user experience in a future refactor.
apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts (2)
304-310: Consider batch update for tab order shifts.The loop updates each workspace's
tabOrderindividually. For small workspace counts this is fine, but if performance becomes a concern, consider using a raw SQL update with increment expression.
1179-1190: N+1 query pattern is acceptable for typical project sizes.Each worktree triggers a separate query to find its workspace. For the expected small number of worktrees per project, this is fine. Consider using a join if this becomes a performance concern with larger datasets.
apps/desktop/src/lib/trpc/routers/projects/projects.ts (2)
532-538: Unusual query pattern: tautological where clause.The condition
eq(projects.tabOrder, projects.tabOrder)is always true for non-null values. This then requires filtering in JS (line 537). Consider usingisNotNull(projects.tabOrder)directly in the query for clarity and to push filtering to the database.🔎 Suggested fix
const activeProjects = localDb .select() .from(projects) - .where(eq(projects.tabOrder, projects.tabOrder)) // Just get all with non-null tabOrder + .where(isNotNull(projects.tabOrder)) .all() - .filter((p) => p.tabOrder !== null) .sort((a, b) => (a.tabOrder ?? 0) - (b.tabOrder ?? 0));Note: You'll need to import
isNotNullfromdrizzle-orm(it's already used inworkspaces.ts).
622-629: Inconsistent settings update pattern.This uses
localDb.update(settings).set(...).where(...)directly, while other routers useinsert(...).onConflictDoUpdate(...). If the settings row doesn't exist, this update will silently do nothing.Consider using the same upsert pattern for consistency:
🔎 Suggested fix
- localDb - .update(settings) - .set({ - lastActiveWorkspaceId: remainingWorkspaces[0]?.id ?? null, - }) - .where(eq(settings.id, 1)) - .run(); + localDb + .insert(settings) + .values({ id: 1, lastActiveWorkspaceId: remainingWorkspaces[0]?.id ?? null }) + .onConflictDoUpdate({ + target: settings.id, + set: { lastActiveWorkspaceId: remainingWorkspaces[0]?.id ?? null }, + }) + .run();
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (44)
apps/admin/package.jsonapps/admin/src/proxy.tsapps/desktop/electron-builder.tsapps/desktop/electron.vite.config.tsapps/desktop/package.jsonapps/desktop/scripts/copy-native-modules.tsapps/desktop/src/lib/trpc/routers/changes/branches.tsapps/desktop/src/lib/trpc/routers/config/config.tsapps/desktop/src/lib/trpc/routers/external/helpers.tsapps/desktop/src/lib/trpc/routers/external/index.tsapps/desktop/src/lib/trpc/routers/projects/projects.tsapps/desktop/src/lib/trpc/routers/settings/index.tsapps/desktop/src/lib/trpc/routers/terminal/terminal.tsapps/desktop/src/lib/trpc/routers/workspaces/utils/github/github.tsapps/desktop/src/lib/trpc/routers/workspaces/utils/worktree.tsapps/desktop/src/lib/trpc/routers/workspaces/workspaces.test.tsapps/desktop/src/lib/trpc/routers/workspaces/workspaces.tsapps/desktop/src/main/index.tsapps/desktop/src/main/lib/db/index.tsapps/desktop/src/main/lib/db/schemas.tsapps/desktop/src/main/lib/local-db/index.tsapps/desktop/src/main/lib/notification-sound.tsapps/desktop/src/main/windows/main.tsapps/desktop/src/renderer/components/OpenInButton/OpenInButton.tsxapps/desktop/src/renderer/screens/main/components/SettingsView/PresetsSettings/types.tsapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksList/ChecksList.tsxapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksList/components/CheckItemRow/CheckItemRow.tsxapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksSummary/ChecksSummary.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/TabsCommandDialog/index.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/index.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceFooter/components/WorkspaceFooterRight/WorkspaceFooterRight.tsxapps/desktop/test-setup.tspackages/db/src/index.tspackages/local-db/drizzle.config.tspackages/local-db/drizzle/0000_initial_schema.sqlpackages/local-db/drizzle/meta/0000_snapshot.jsonpackages/local-db/drizzle/meta/_journal.jsonpackages/local-db/package.jsonpackages/local-db/src/index.tspackages/local-db/src/schema/index.tspackages/local-db/src/schema/relations.tspackages/local-db/src/schema/schema.tspackages/local-db/src/schema/zod.tspackages/local-db/tsconfig.json
💤 Files with no reviewable changes (4)
- packages/db/src/index.ts
- apps/desktop/src/main/lib/db/schemas.ts
- apps/desktop/src/lib/trpc/routers/workspaces/workspaces.test.ts
- apps/desktop/src/main/lib/db/index.ts
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Avoid using any type in TypeScript - maintain type safety unless absolutely necessary
Files:
packages/local-db/src/schema/relations.tspackages/local-db/src/index.tsapps/desktop/src/main/lib/notification-sound.tsapps/desktop/src/lib/trpc/routers/external/helpers.tsapps/desktop/src/lib/trpc/routers/config/config.tsapps/desktop/electron.vite.config.tsapps/desktop/src/renderer/screens/main/components/SettingsView/PresetsSettings/types.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/TabsCommandDialog/index.tsxapps/desktop/src/lib/trpc/routers/terminal/terminal.tsapps/desktop/src/main/lib/local-db/index.tsapps/desktop/src/lib/trpc/routers/changes/branches.tspackages/local-db/src/schema/index.tsapps/desktop/src/lib/trpc/routers/settings/index.tspackages/local-db/src/schema/schema.tsapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksSummary/ChecksSummary.tsxpackages/local-db/src/schema/zod.tsapps/desktop/electron-builder.tsapps/desktop/src/main/windows/main.tsapps/desktop/src/lib/trpc/routers/workspaces/utils/github/github.tsapps/desktop/src/lib/trpc/routers/projects/projects.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/index.tsxapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksList/ChecksList.tsxapps/desktop/test-setup.tsapps/admin/src/proxy.tsapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksList/components/CheckItemRow/CheckItemRow.tsxapps/desktop/src/lib/trpc/routers/external/index.tsapps/desktop/scripts/copy-native-modules.tsapps/desktop/src/lib/trpc/routers/workspaces/workspaces.tsapps/desktop/src/lib/trpc/routers/workspaces/utils/worktree.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceFooter/components/WorkspaceFooterRight/WorkspaceFooterRight.tsxpackages/local-db/drizzle.config.tsapps/desktop/src/renderer/components/OpenInButton/OpenInButton.tsxapps/desktop/src/main/index.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Run Biome for formatting, linting, import organization, and safe fixes at the root level using bun run lint:fix
Files:
packages/local-db/src/schema/relations.tspackages/local-db/src/index.tsapps/desktop/src/main/lib/notification-sound.tsapps/desktop/src/lib/trpc/routers/external/helpers.tsapps/desktop/src/lib/trpc/routers/config/config.tsapps/desktop/electron.vite.config.tsapps/desktop/src/renderer/screens/main/components/SettingsView/PresetsSettings/types.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/TabsCommandDialog/index.tsxapps/desktop/src/lib/trpc/routers/terminal/terminal.tsapps/desktop/src/main/lib/local-db/index.tsapps/desktop/src/lib/trpc/routers/changes/branches.tspackages/local-db/src/schema/index.tsapps/desktop/src/lib/trpc/routers/settings/index.tspackages/local-db/src/schema/schema.tsapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksSummary/ChecksSummary.tsxpackages/local-db/src/schema/zod.tsapps/desktop/electron-builder.tsapps/desktop/src/main/windows/main.tsapps/desktop/src/lib/trpc/routers/workspaces/utils/github/github.tsapps/desktop/src/lib/trpc/routers/projects/projects.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/index.tsxapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksList/ChecksList.tsxapps/desktop/test-setup.tsapps/admin/src/proxy.tsapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksList/components/CheckItemRow/CheckItemRow.tsxapps/desktop/src/lib/trpc/routers/external/index.tsapps/desktop/scripts/copy-native-modules.tsapps/desktop/src/lib/trpc/routers/workspaces/workspaces.tsapps/desktop/src/lib/trpc/routers/workspaces/utils/worktree.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceFooter/components/WorkspaceFooterRight/WorkspaceFooterRight.tsxpackages/local-db/drizzle.config.tsapps/desktop/src/renderer/components/OpenInButton/OpenInButton.tsxapps/desktop/src/main/index.ts
apps/desktop/src/{main,renderer,preload}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use type-safe IPC communication - define channel types in apps/desktop/src/shared/ipc-channels.ts before implementing handlers
Files:
apps/desktop/src/main/lib/notification-sound.tsapps/desktop/src/renderer/screens/main/components/SettingsView/PresetsSettings/types.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/TabsCommandDialog/index.tsxapps/desktop/src/main/lib/local-db/index.tsapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksSummary/ChecksSummary.tsxapps/desktop/src/main/windows/main.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/index.tsxapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksList/ChecksList.tsxapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksList/components/CheckItemRow/CheckItemRow.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceFooter/components/WorkspaceFooterRight/WorkspaceFooterRight.tsxapps/desktop/src/renderer/components/OpenInButton/OpenInButton.tsxapps/desktop/src/main/index.ts
apps/desktop/src/main/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Accept object parameters in IPC handlers - do not use positional parameters in ipcMain.handle()
Files:
apps/desktop/src/main/lib/notification-sound.tsapps/desktop/src/main/lib/local-db/index.tsapps/desktop/src/main/windows/main.tsapps/desktop/src/main/index.ts
apps/desktop/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)
apps/desktop/**/*.{ts,tsx}: For Electron interprocess communication, ALWAYS use tRPC as defined insrc/lib/trpc
Use alias as defined intsconfig.jsonwhen possible
Prefer zustand for state management if it makes sense. Do not use effect unless absolutely necessary.
For tRPC subscriptions with trpc-electron, ALWAYS use the observable pattern from@trpc/server/observableinstead of async generators, as the library explicitly checksisObservable(result)and throws an error otherwise
Files:
apps/desktop/src/main/lib/notification-sound.tsapps/desktop/src/lib/trpc/routers/external/helpers.tsapps/desktop/src/lib/trpc/routers/config/config.tsapps/desktop/electron.vite.config.tsapps/desktop/src/renderer/screens/main/components/SettingsView/PresetsSettings/types.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/TabsCommandDialog/index.tsxapps/desktop/src/lib/trpc/routers/terminal/terminal.tsapps/desktop/src/main/lib/local-db/index.tsapps/desktop/src/lib/trpc/routers/changes/branches.tsapps/desktop/src/lib/trpc/routers/settings/index.tsapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksSummary/ChecksSummary.tsxapps/desktop/electron-builder.tsapps/desktop/src/main/windows/main.tsapps/desktop/src/lib/trpc/routers/workspaces/utils/github/github.tsapps/desktop/src/lib/trpc/routers/projects/projects.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/index.tsxapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksList/ChecksList.tsxapps/desktop/test-setup.tsapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksList/components/CheckItemRow/CheckItemRow.tsxapps/desktop/src/lib/trpc/routers/external/index.tsapps/desktop/scripts/copy-native-modules.tsapps/desktop/src/lib/trpc/routers/workspaces/workspaces.tsapps/desktop/src/lib/trpc/routers/workspaces/utils/worktree.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceFooter/components/WorkspaceFooterRight/WorkspaceFooterRight.tsxapps/desktop/src/renderer/components/OpenInButton/OpenInButton.tsxapps/desktop/src/main/index.ts
**/{components,features}/**/*.{ts,tsx,test.ts,test.tsx,stories.tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Co-locate component dependencies (utils, hooks, constants, config, tests, stories) next to the file using them
Files:
apps/desktop/src/renderer/screens/main/components/SettingsView/PresetsSettings/types.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/TabsCommandDialog/index.tsxapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksSummary/ChecksSummary.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/index.tsxapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksList/ChecksList.tsxapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksList/components/CheckItemRow/CheckItemRow.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceFooter/components/WorkspaceFooterRight/WorkspaceFooterRight.tsxapps/desktop/src/renderer/components/OpenInButton/OpenInButton.tsx
apps/desktop/src/renderer/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Never import Node.js modules in renderer process or shared code - use only in main process (src/main/)
Files:
apps/desktop/src/renderer/screens/main/components/SettingsView/PresetsSettings/types.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/TabsCommandDialog/index.tsxapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksSummary/ChecksSummary.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/index.tsxapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksList/ChecksList.tsxapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksList/components/CheckItemRow/CheckItemRow.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceFooter/components/WorkspaceFooterRight/WorkspaceFooterRight.tsxapps/desktop/src/renderer/components/OpenInButton/OpenInButton.tsx
**/{components,features}/**/[!.]*.tsx
📄 CodeRabbit inference engine (AGENTS.md)
Organize project structure with one folder per component: ComponentName/ComponentName.tsx with index.ts barrel export
Files:
apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/TabsCommandDialog/index.tsxapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksSummary/ChecksSummary.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/index.tsxapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksList/ChecksList.tsxapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksList/components/CheckItemRow/CheckItemRow.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceFooter/components/WorkspaceFooterRight/WorkspaceFooterRight.tsxapps/desktop/src/renderer/components/OpenInButton/OpenInButton.tsx
**/*.{tsx,css}
📄 CodeRabbit inference engine (AGENTS.md)
Use React + TailwindCSS v4 + shadcn/ui for UI development
Files:
apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/TabsCommandDialog/index.tsxapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksSummary/ChecksSummary.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/index.tsxapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksList/ChecksList.tsxapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksList/components/CheckItemRow/CheckItemRow.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceFooter/components/WorkspaceFooterRight/WorkspaceFooterRight.tsxapps/desktop/src/renderer/components/OpenInButton/OpenInButton.tsx
**/{components,features}/**/*.tsx
📄 CodeRabbit inference engine (AGENTS.md)
**/{components,features}/**/*.tsx: Nest components in parent's components/ folder if used only once, promote to highest shared parent's components/ if used 2+ times
Use one component per file - do not combine multiple components in a single file
Files:
apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/TabsCommandDialog/index.tsxapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksSummary/ChecksSummary.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/index.tsxapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksList/ChecksList.tsxapps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksList/components/CheckItemRow/CheckItemRow.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceFooter/components/WorkspaceFooterRight/WorkspaceFooterRight.tsxapps/desktop/src/renderer/components/OpenInButton/OpenInButton.tsx
apps/desktop/src/main/index.ts
📄 CodeRabbit inference engine (AGENTS.md)
Load environment variables in src/main/index.ts and electron.vite.config.ts with override: true before other imports
Files:
apps/desktop/src/main/index.ts
🧠 Learnings (11)
📓 Common learnings
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-18T23:19:10.415Z
Learning: Applies to packages/db/src/**/*.{ts,tsx} : Store database schema in packages/db/src/ and use Drizzle ORM for schema management
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-18T23:19:10.415Z
Learning: Applies to apps/api/src/**/*.{ts,tsx} : Use Drizzle ORM for all database operations
📚 Learning: 2025-12-18T23:19:10.415Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-18T23:19:10.415Z
Learning: Applies to packages/db/src/**/*.{ts,tsx} : Store database schema in packages/db/src/ and use Drizzle ORM for schema management
Applied to files:
packages/local-db/src/schema/relations.tspackages/local-db/src/index.tsapps/desktop/src/lib/trpc/routers/config/config.tsapps/desktop/src/lib/trpc/routers/terminal/terminal.tsapps/desktop/src/main/lib/local-db/index.tsapps/desktop/src/lib/trpc/routers/changes/branches.tspackages/local-db/src/schema/index.tspackages/local-db/package.jsonpackages/local-db/src/schema/schema.tspackages/local-db/drizzle/0000_initial_schema.sqlpackages/local-db/src/schema/zod.tsapps/desktop/src/main/windows/main.tsapps/desktop/src/lib/trpc/routers/projects/projects.tspackages/local-db/tsconfig.jsonapps/admin/src/proxy.tspackages/local-db/drizzle/meta/0000_snapshot.jsonapps/admin/package.jsonapps/desktop/src/lib/trpc/routers/workspaces/workspaces.tsapps/desktop/src/lib/trpc/routers/workspaces/utils/worktree.tspackages/local-db/drizzle.config.ts
📚 Learning: 2025-12-18T23:19:10.415Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-18T23:19:10.415Z
Learning: Applies to apps/api/src/**/*.{ts,tsx} : Use Drizzle ORM for all database operations
Applied to files:
packages/local-db/src/schema/relations.tsapps/desktop/src/lib/trpc/routers/config/config.tsapps/desktop/src/lib/trpc/routers/terminal/terminal.tsapps/desktop/src/main/lib/local-db/index.tsapps/desktop/src/lib/trpc/routers/changes/branches.tspackages/local-db/package.jsonpackages/local-db/src/schema/schema.tspackages/local-db/tsconfig.jsonapps/admin/src/proxy.tsapps/admin/package.jsonapps/desktop/src/lib/trpc/routers/workspaces/workspaces.tspackages/local-db/drizzle.config.ts
📚 Learning: 2025-12-21T04:39:28.543Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-12-21T04:39:28.543Z
Learning: Applies to apps/desktop/**/*.{ts,tsx} : For Electron interprocess communication, ALWAYS use tRPC as defined in `src/lib/trpc`
Applied to files:
apps/desktop/src/lib/trpc/routers/external/helpers.tsapps/desktop/src/lib/trpc/routers/terminal/terminal.tsapps/desktop/src/main/windows/main.tsapps/desktop/test-setup.tsapps/desktop/src/lib/trpc/routers/external/index.ts
📚 Learning: 2025-12-18T23:19:10.415Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-18T23:19:10.415Z
Learning: Applies to apps/desktop/src/renderer/**/*.{ts,tsx} : Never import Node.js modules in renderer process or shared code - use only in main process (src/main/)
Applied to files:
apps/desktop/src/lib/trpc/routers/external/helpers.tsapps/desktop/electron.vite.config.tsapps/desktop/scripts/copy-native-modules.tsapps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceFooter/components/WorkspaceFooterRight/WorkspaceFooterRight.tsxapps/desktop/src/renderer/components/OpenInButton/OpenInButton.tsxapps/desktop/src/main/index.ts
📚 Learning: 2025-12-18T23:19:10.415Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-18T23:19:10.415Z
Learning: Applies to apps/desktop/src/main/index.ts : Load environment variables in src/main/index.ts and electron.vite.config.ts with override: true before other imports
Applied to files:
apps/desktop/electron.vite.config.tsapps/desktop/src/main/index.ts
📚 Learning: 2025-12-18T23:19:10.415Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-18T23:19:10.415Z
Learning: Create database migrations by modifying Drizzle schema in packages/db/src/schema and running drizzle-kit generate with snake_case migration names
Applied to files:
packages/local-db/drizzle/0000_initial_schema.sqlpackages/local-db/drizzle/meta/0000_snapshot.jsonpackages/local-db/drizzle.config.ts
📚 Learning: 2025-12-21T04:39:28.543Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-12-21T04:39:28.543Z
Learning: Applies to apps/desktop/**/*.{ts,tsx} : Use alias as defined in `tsconfig.json` when possible
Applied to files:
packages/local-db/tsconfig.jsonapps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/index.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceFooter/components/WorkspaceFooterRight/WorkspaceFooterRight.tsxapps/desktop/src/renderer/components/OpenInButton/OpenInButton.tsx
📚 Learning: 2025-12-18T23:19:10.415Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-18T23:19:10.415Z
Learning: Applies to apps/desktop/src/{main,renderer,preload}/**/*.{ts,tsx} : Use type-safe IPC communication - define channel types in apps/desktop/src/shared/ipc-channels.ts before implementing handlers
Applied to files:
apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/index.tsxapps/desktop/test-setup.ts
📚 Learning: 2025-12-18T23:19:10.415Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-18T23:19:10.415Z
Learning: Applies to src/components/{ui,ai-elements,react-flow}/**/*.tsx : Use kebab-case single files for shadcn/ui components in src/components/ui/, src/components/ai-elements, and src/components/react-flow/ directories
Applied to files:
apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksList/components/CheckItemRow/CheckItemRow.tsx
📚 Learning: 2025-12-18T23:19:10.415Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-18T23:19:10.415Z
Learning: Applies to **/*.{tsx,css} : Use React + TailwindCSS v4 + shadcn/ui for UI development
Applied to files:
apps/desktop/package.json
🧬 Code graph analysis (12)
packages/local-db/src/schema/relations.ts (1)
packages/local-db/src/schema/schema.ts (3)
projects(15-40)worktrees(48-70)workspaces(78-109)
apps/desktop/src/lib/trpc/routers/config/config.ts (2)
apps/desktop/src/main/lib/local-db/index.ts (1)
localDb(80-80)packages/local-db/src/schema/schema.ts (1)
projects(15-40)
apps/desktop/src/main/lib/local-db/index.ts (2)
apps/desktop/src/main/lib/app-environment.ts (2)
DB_PATH(8-8)SUPERSET_HOME_DIR(5-5)packages/local-db/src/schema/schema.ts (4)
projects(15-40)worktrees(48-70)workspaces(78-109)settings(117-128)
apps/desktop/src/lib/trpc/routers/changes/branches.ts (2)
apps/desktop/src/main/lib/local-db/index.ts (1)
localDb(80-80)packages/local-db/src/schema/schema.ts (1)
worktrees(48-70)
packages/local-db/src/schema/schema.ts (3)
packages/local-db/src/schema/zod.ts (5)
GitStatus(12-12)GitHubStatus(48-48)WorkspaceType(68-68)ExternalApp(97-97)TerminalPreset(61-61)apps/desktop/src/lib/trpc/routers/external/helpers.ts (1)
ExternalApp(97-97)apps/desktop/src/renderer/screens/main/components/SettingsView/PresetsSettings/types.ts (1)
TerminalPreset(3-3)
packages/local-db/src/schema/zod.ts (2)
apps/desktop/src/renderer/screens/main/components/SettingsView/PresetsSettings/types.ts (1)
TerminalPreset(3-3)apps/desktop/src/lib/trpc/routers/external/helpers.ts (2)
EXTERNAL_APPS(97-97)ExternalApp(97-97)
apps/desktop/src/main/windows/main.ts (2)
apps/desktop/src/main/lib/local-db/index.ts (1)
localDb(80-80)packages/local-db/src/schema/schema.ts (2)
workspaces(78-109)worktrees(48-70)
apps/desktop/src/lib/trpc/routers/projects/projects.ts (4)
packages/local-db/src/schema/schema.ts (4)
SelectProject(43-43)projects(15-40)workspaces(78-109)settings(117-128)apps/desktop/src/main/lib/local-db/index.ts (1)
localDb(80-80)apps/desktop/src/lib/trpc/routers/projects/utils/colors/colors.ts (1)
assignRandomColor(3-7)apps/desktop/src/lib/trpc/routers/projects/utils/colors/index.ts (1)
assignRandomColor(1-1)
apps/desktop/src/lib/trpc/routers/external/index.ts (2)
apps/desktop/src/main/lib/local-db/index.ts (1)
localDb(80-80)packages/local-db/src/schema/schema.ts (1)
settings(117-128)
apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts (2)
apps/desktop/src/main/lib/local-db/index.ts (1)
localDb(80-80)packages/local-db/src/schema/schema.ts (5)
projects(15-40)worktrees(48-70)workspaces(78-109)settings(117-128)SelectWorktree(73-73)
apps/desktop/src/lib/trpc/routers/workspaces/utils/worktree.ts (2)
apps/desktop/src/main/lib/local-db/index.ts (1)
localDb(80-80)packages/local-db/src/schema/schema.ts (3)
worktrees(48-70)SelectWorkspace(112-112)projects(15-40)
apps/desktop/src/main/index.ts (1)
apps/desktop/src/main/lib/local-db/index.ts (1)
localDb(80-80)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: Deploy Marketing
- GitHub Check: Deploy Web
- GitHub Check: Deploy Admin
- GitHub Check: Deploy API
- GitHub Check: Deploy Docs
- GitHub Check: Build
- GitHub Check: Build - macOS (arm64)
🔇 Additional comments (62)
packages/local-db/tsconfig.json (1)
1-11: LGTM! Well-configured TypeScript setup for the local-db package.The configuration properly:
- Extends the shared internal package config for consistency
- Defines a path alias
@/*for cleaner imports- Includes the Drizzle config file for type checking
- Follows standard TypeScript and monorepo conventions
This aligns well with the migration to SQLite and Drizzle ORM.
apps/admin/package.json (2)
28-28: No action needed. The drizzle-orm version 0.45.1 is the latest stable release with no known direct vulnerabilities.
28-28: No action needed. Version 0.45.1 is the latest version of drizzle-orm and no direct vulnerabilities have been found for this package. The dependency addition is consistent with the monorepo architecture where multiple packages (apps/api, apps/desktop, packages/local-db, packages/trpc) maintain direct drizzle-orm dependencies alongside the centralized schema management in @superset/db.Likely an incorrect or invalid review comment.
apps/admin/src/proxy.ts (1)
2-2: Import paths updated correctly for Drizzle ORM migration.The changes properly separate the database client from schema definitions by importing
dbfrom@superset/db/clientandusersfrom@superset/db/schema. The direct import ofeqfromdrizzle-ormfollows Drizzle best practices, and the relational query syntax (db.query.users.findFirst()) is correctly implemented with full type safety.apps/desktop/scripts/copy-native-modules.ts (1)
19-19: LGTM! Proper native module support added for better-sqlite3.The addition of "better-sqlite3" to the NATIVE_MODULES array correctly ensures that the SQLite native module is properly packaged by electron-builder, which is essential for the local database migration.
apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksList/components/CheckItemRow/CheckItemRow.tsx (1)
1-1: LGTM! Type import correctly updated to local-db package.The import source update aligns with the migration to the centralized
@superset/local-dbpackage for all database-related types.apps/desktop/src/renderer/screens/main/components/SettingsView/PresetsSettings/types.ts (1)
1-1: LGTM! Type import correctly migrated.Consistent with the broader migration to use
@superset/local-dbas the central source for database types.packages/local-db/drizzle.config.ts (1)
3-7: LGTM! Drizzle configuration properly set up.The configuration correctly points to the schema file and sets up SQLite dialect for the local database. This aligns with the established pattern of using Drizzle ORM for schema management.
Based on learnings, this follows the recommended approach for database schema management.
packages/local-db/drizzle/0000_initial_schema.sql (1)
1-55: LGTM! Well-structured initial schema migration.The migration properly establishes:
- Four core tables with appropriate columns and constraints
- Foreign key relationships with cascade deletion for data integrity
- Indexes on frequently queried fields for performance
- Settings table uses a singleton pattern (id DEFAULT 1) which is appropriate for global application settings
Based on learnings, this follows the recommended approach for creating database migrations with Drizzle.
apps/desktop/src/lib/trpc/routers/changes/branches.ts (1)
64-87: LGTM! Clean migration to Drizzle ORM.The database access has been correctly migrated from in-memory storage to SQLite with Drizzle ORM:
- Query pattern using
select().from().where().get()is idiomatic Drizzle- Update pattern using
update().set().where().run()is correct- The gitStatus handling properly preserves existing status while updating the branch, or sets to null if no prior status exists
Based on learnings, this follows the recommended approach for using Drizzle ORM for all database operations.
packages/local-db/src/schema/zod.ts (1)
1-97: LGTM! Comprehensive and well-structured Zod schemas.The schema definitions are well-organized with:
- Clear JSDoc comments for each domain entity
- Proper Zod validation patterns (enums, objects, arrays, optional fields)
- Type-safe inference using
z.infer<typeof schema>- EXTERNAL_APPS constant correctly typed with
as constfor literal type narrowingThese schemas provide strong runtime validation and TypeScript type safety for the local database layer.
apps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceFooter/components/WorkspaceFooterRight/WorkspaceFooterRight.tsx (1)
1-1: LGTM! Type import correctly updated.The ExternalApp type import has been properly migrated to
@superset/local-db, maintaining type safety while aligning with the centralized schema package.apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/index.tsx (1)
1-1: LGTM! Type import successfully migrated to local-db package.The import path update for
TerminalPresetis consistent with the broader migration to the@superset/local-dbpackage. The type usage throughout the component remains unchanged.apps/desktop/src/renderer/components/OpenInButton/OpenInButton.tsx (1)
1-1: LGTM! Type import migrated correctly.The
ExternalApptype import has been successfully updated to use the new@superset/local-dbpackage. No runtime behavior changes.apps/desktop/src/lib/trpc/routers/external/helpers.ts (1)
3-3: LGTM! Import and re-export updated correctly.Both the
EXTERNAL_APPSconstant andExternalApptype have been migrated to@superset/local-db. The re-export at line 97 maintains compatibility for existing consumers.apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksSummary/ChecksSummary.tsx (1)
1-1: LGTM! Type import updated correctly.The
CheckItemtype import has been successfully migrated to the@superset/local-dbpackage.packages/local-db/src/index.ts (1)
1-1: LGTM! Barrel export correctly established.The barrel export provides a clean entry point for the
@superset/local-dbpackage, allowing consumers to import schema types and entities directly from the package root.apps/desktop/src/lib/trpc/routers/workspaces/utils/github/github.ts (1)
3-3: LGTM! Type imports migrated successfully.Both
CheckItemandGitHubStatustypes have been correctly updated to import from@superset/local-db. No runtime behavior changes.apps/desktop/src/renderer/screens/main/components/WorkspaceView/Sidebar/TabsView/TabsCommandDialog/index.tsx (1)
1-1: LGTM! Type import updated correctly.The
TerminalPresettype import has been successfully migrated to@superset/local-db.packages/local-db/drizzle/meta/_journal.json (1)
1-13: LGTM! Standard Drizzle migration journal.This is a properly formatted Drizzle migration journal file that tracks the initial schema migration. The file is auto-generated and follows the standard Drizzle metadata format.
apps/desktop/electron-builder.ts (2)
36-40: LGTM! Native module unpacking configured correctly.Adding
better-sqlite3toasarUnpackfollows the same pattern asnode-ptyand is required for native modules to function properly in the packaged Electron app.
50-63: LGTM! Build configuration for migrations and native modules.The copy rules correctly handle:
- Database migrations from the Vite build output to the packaged resources
- The
better-sqlite3native module following the same pattern asnode-ptypackages/local-db/src/schema/index.ts (1)
1-3: LGTM! Clean barrel export for schema module.Standard pattern for consolidating public exports. Aligns with the coding guidelines for Drizzle ORM schema management.
apps/desktop/src/main/index.ts (1)
10-15: LGTM! Database initialization via import side-effect.The
localDbimport triggers synchronous SQLite initialization (schema migrations + legacy data import). Theconsole.logserves dual purposes: confirming database readiness and preventing the import from being tree-shaken.apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceHoverCard/components/ChecksList/ChecksList.tsx (1)
1-1: LGTM! Type import migrated to centralized package.The type-only import from
@superset/local-dbis safe for renderer code since types are erased at compile time—no Node.js runtime dependency is introduced.apps/desktop/src/lib/trpc/routers/terminal/terminal.ts (3)
3-6: LGTM! Imports updated for Drizzle ORM migration.Correctly imports the schema tables,
eqhelper, andlocalDbinstance for the database migration.
53-70: LGTM! Workspace and project lookups migrated to Drizzle.The queries follow the correct Drizzle pattern:
localDb.select().from(table).where(eq(...)).get(). The.get()method appropriately returns a single row orundefined.
178-197: LGTM! Added proper null guard for worktreeId.Good defensive programming—checking
workspace.worktreeIdbefore querying theworktreestable prevents unnecessary queries and potential issues whenworktreeIdis null (e.g., for non-worktree workspace types).apps/desktop/src/main/windows/main.ts (2)
2-3: LGTM! Imports updated for Drizzle ORM integration.Correctly imports schema tables, the
eqhelper, and thelocalDbinstance.Also applies to: 8-8
92-106: LGTM! Notification handler migrated to Drizzle queries.The migration correctly:
- Guards against missing
workspaceIdbefore querying- Conditionally fetches the worktree only when
workspace.worktreeIdexists- Preserves the fallback chain for
workspaceName- Maintains error handling with the existing try-catch block
apps/desktop/src/lib/trpc/routers/config/config.ts (4)
3-5: LGTM! Imports updated for Drizzle ORM migration.Correctly imports the
projectsschema,eqhelper, andlocalDbinstance.
46-50: LGTM! Query migrated to Drizzle ORM.Follows the correct pattern for single-row lookups.
66-72: LGTM! Update operation uses correct Drizzle pattern.The
.update().set().where().run()chain is the correct pattern for mutations in Drizzle with better-sqlite3.
79-98: LGTM! Remaining queries migrated consistently.Both
getConfigFilePathandgetConfigContentfollow the same Drizzle query pattern with proper null handling.packages/local-db/drizzle/meta/0000_snapshot.json (1)
1-383: LGTM! Drizzle migration snapshot generated correctly.The schema snapshot properly captures:
- Tables:
projects,settings,workspaces,worktreeswith appropriate column types- Foreign keys: Cascade deletes configured for referential integrity
- Indexes: Appropriate indexes on
project_id,worktree_id,last_opened_at,branch, andmain_repo_pathfor query optimization- Settings singleton: Uses
idwith default value1for single-row configurationThis file is auto-generated by
drizzle-kit generate—manual edits should be avoided.apps/desktop/src/lib/trpc/routers/external/index.ts (1)
84-85: LGTM - Good fallback handling!The settings read with a sensible default fallback to "cursor" is well-implemented. The optional chaining ensures graceful handling when no settings row exists yet.
apps/desktop/src/main/lib/notification-sound.ts (1)
19-20: LGTM - Well-structured database query with proper fallbacks!The migration to localDb is clean with appropriate error handling and fallback logic. The optional chaining and null coalescing provide a robust default chain.
packages/local-db/src/schema/relations.ts (1)
1-26: LGTM - Relations correctly mirror the database schema!The Drizzle ORM relations are properly defined and match the foreign key constraints in the schema. The explicit field-to-reference mappings ensure type safety for joins and relational queries.
packages/local-db/package.json (2)
8-13: TypeScript source exports are correct for workspace-only packages.The package exports TypeScript source files (
.ts) directly, which is appropriate for internal workspace packages that are never published to npm. The consuming packages (desktop app) will transpile these as part of their build.
22-22: No action needed. drizzle-orm 0.45.1 and drizzle-kit 0.31.8 are compatible versions with no known incompatibilities.apps/desktop/electron.vite.config.ts (2)
50-63: LGTM - Migration copying is properly implemented!The database migrations are correctly copied from the local-db package to the resources directory with proper cleanup and existence checks. This aligns with the migration path resolution logic in the local-db initialization.
104-104: Good - Native module correctly externalized.The
better-sqlite3native module is properly externalized, preventing Vite from attempting to bundle it. This is essential for native modules in Electron.apps/desktop/src/main/lib/local-db/index.ts (2)
92-214: Legacy migration logic is comprehensive and well-structured.The
migrateFromLegacyDb()function properly:
- Checks for existing data before migrating
- Handles missing fields with sensible defaults
- Backs up the original file
- Has appropriate error handling that doesn't break app startup
The branch reconstruction logic (lines 158-164) for workspaces is particularly good, handling the case where legacy data may be missing the branch field.
74-75: Good choice of WAL mode for SQLite.Enabling WAL (Write-Ahead Logging) mode improves concurrency and performance, allowing readers to proceed while writes are happening. This is appropriate for an Electron desktop app with multiple potential access points.
apps/desktop/package.json (1)
61-61: Native module packaging for better-sqlite3 is properly configured.All requirements are already implemented:
- Module is externalized in electron.vite.config.ts (line 104)
- ASAR unpacking is configured in electron-builder.ts (line 36) with
"**/node_modules/better-sqlite3/**/*"- Binary is explicitly included in the packaged app via the files array (lines 59-63)
- Build strategy properly handles pre-compiled dependencies via
npmRebuild: falseapps/desktop/src/lib/trpc/routers/settings/index.ts (3)
12-18: LGTM!The
getSettings()helper correctly ensures a settings row exists before any read/write operation, using an idempotent insert with a fixedid: 1. This is a clean pattern for singleton settings management.
49-56: LGTM!The upsert pattern using
insert().values().onConflictDoUpdate()is idiomatic Drizzle ORM for singleton settings. The in-memory array mutation before persisting is appropriate for this single-user desktop context.
120-147: LGTM!The self-healing pattern for invalid ringtone IDs is a good defensive approach. It logs a warning for debugging while automatically correcting corrupted state.
apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts (6)
121-161: LGTM!The workspace creation flow correctly:
- Inserts the worktree with
.returning().get()to capture the new record- Calculates the next
tabOrderfrom existing workspaces- Links the workspace to the worktree via
worktreeIdThe non-atomic nature of these operations is acceptable for a single-user desktop application.
562-568: LGTM!The type assertion for
workspace.typeis necessary since Drizzle infersstringfrom the text column despite the$type<WorkspaceType>()annotation. The explicit interface ingroupsMapcorrectly documents the expected shape.
609-648: LGTM!The lazy migration pattern for
baseBranchcorrectly distinguishes between:
undefined: not yet attempted detectionnull: attempted but not found (avoids retry)- string value: successfully detected
This prevents redundant detection attempts on subsequent calls.
905-910: LGTM!The explicit deletion of both workspace and worktree records is correct. While the schema defines
onDelete: cascadeonworktreeId, explicitly deleting both records provides clearer intent and works correctly regardless of deletion order.
1004-1011: LGTM!Good bounds checking on
fromIndexandtoIndexbefore performing the reorder operation.
1330-1331: LGTM!The
closemutation correctly deletes only the workspace record while preserving the worktree. This aligns with the semantic distinction fromdelete, which removes both the workspace and the underlying git worktree.apps/desktop/src/lib/trpc/routers/projects/projects.ts (3)
45-75: LGTM!The
upsertProjecthelper correctly handles both update and insert cases. Returning a manually constructed object on update (line 60) avoids an extra DB query and is safe here since we control exactly what's being updated.
85-142: LGTM!The
extractRepoNameutility is well-implemented with:
- Support for both HTTPS and SSH-style git URLs
- Defensive validation via
SAFE_REPO_NAME_REGEXto prevent path traversal- Proper handling of edge cases (percent encoding, trailing slashes, query strings)
596-601: LGTM!Good use of
inArrayfor bulk deletion of workspaces. This is more efficient than deleting one-by-one in a loop.apps/desktop/test-setup.ts (1)
65-112: LGTM!The extended Electron mocks cover additional APIs (clipboard, screen, Notification, Menu) needed for testing. The mock implementations return sensible defaults that won't cause test failures.
packages/local-db/src/schema/schema.ts (4)
15-43: LGTM!The
projectstable schema is well-designed with:
- UUID primary keys for distributed-safe ID generation
- Appropriate indices on
mainRepoPath(for upsert lookups) andlastOpenedAt(for recents sorting)- Integer timestamps which are SQLite-optimal
- Nullable
tabOrderto distinguish active vs inactive projectsBased on learnings, this correctly uses Drizzle ORM for schema management.
48-73: LGTM!The
worktreestable correctly:
- Uses cascading deletes to clean up when parent project is deleted
- Stores complex
gitStatusandgithubStatusas JSON columns- Includes appropriate indices for
projectIdandbranchlookups
78-112: LGTM!The
workspacestable correctly models the dual-type architecture:
worktreeIdis nullable to support branch-based workspaces- Both FKs have cascading deletes for proper cleanup
- The
$type<WorkspaceType>()annotation provides TypeScript type safety for thetypecolumn
117-131: LGTM!The
settingstable implements a clean singleton pattern withid: integer().default(1). The JSON storage forterminalPresetsis appropriate for the array structure, and the lack of FK onlastActiveWorkspaceIdcorrectly allows the app to handle stale references gracefully.
| id: nanoid(), | ||
| .mutation(({ input }) => { | ||
| const preset: TerminalPreset = { | ||
| id: crypto.randomUUID(), |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Search for the settings router file and check its contents
find apps/desktop/src -name "*.ts" -path "*settings*" | head -20
# Also search for uuid package usage in the desktop app
rg -l "uuid" apps/desktop/src --type ts -A 2 -B 2 | head -20
# Check for crypto imports
rg -n "randomUUID|import.*crypto" apps/desktop/src --type ts | head -30
# Check package.json to see if uuid is a dependency
cat package.json | grep -A 20 '"dependencies"' || cat package.json | grep -A 20 '"devDependencies"'Repository: superset-sh/superset
Length of output: 1335
🏁 Script executed:
head -50 apps/desktop/src/lib/trpc/routers/settings/index.tsRepository: superset-sh/superset
Length of output: 1388
Add missing crypto import to fix runtime error at line 41.
The file uses crypto.randomUUID() without importing the crypto module. Add import crypto from "node:crypto"; at the top of the file, following the pattern already established in other files like apps/desktop/src/main/lib/auth/auth-service.ts.
🤖 Prompt for AI Agents
In apps/desktop/src/lib/trpc/routers/settings/index.ts around line 41, the code
calls crypto.randomUUID() but the crypto module is not imported; add the import
statement import crypto from "node:crypto"; at the top of the file (following
the existing project pattern) so runtime will have crypto available.
| migrate(localDb, { migrationsFolder }); | ||
|
|
||
| console.log("[local-db] Migrations complete"); |
There was a problem hiding this comment.
Critical: No error handling for database migrations.
The migrate() call at line 82 has no error handling. If a migration fails (e.g., corrupt migration file, SQL syntax error, file permission issue), the app will crash during startup with an unhandled exception.
🔎 Add error handling for migrations
-migrate(localDb, { migrationsFolder });
-
-console.log("[local-db] Migrations complete");
+try {
+ migrate(localDb, { migrationsFolder });
+ console.log("[local-db] Migrations complete");
+} catch (error) {
+ console.error("[local-db] Migration failed:", error);
+ // Consider: show error dialog to user or create recovery mechanism
+ throw new Error(`Database migration failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
+}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| migrate(localDb, { migrationsFolder }); | |
| console.log("[local-db] Migrations complete"); | |
| try { | |
| migrate(localDb, { migrationsFolder }); | |
| console.log("[local-db] Migrations complete"); | |
| } catch (error) { | |
| console.error("[local-db] Migration failed:", error); | |
| // Consider: show error dialog to user or create recovery mechanism | |
| throw new Error(`Database migration failed: ${error instanceof Error ? error.message : 'Unknown error'}`); | |
| } |
🤖 Prompt for AI Agents
In apps/desktop/src/main/lib/local-db/index.ts around lines 82 to 84, the
migrate(localDb, { migrationsFolder }) call runs without error handling; wrap
the migration call in a try/catch (and await it if it returns a Promise) so
migration failures are caught, log the full error details via the existing
logger (or console.error) with a clear message, and then handle the failure
deterministically (e.g., clean shutdown with process.exit(1) or rethrow after
logging) to avoid an unhandled exception crashing the app.
| mock.module("main/lib/local-db", () => ({ | ||
| localDb: { | ||
| select: mock(() => ({ | ||
| from: mock(() => ({ | ||
| where: mock(() => ({ | ||
| get: mock(() => null), | ||
| all: mock(() => []), | ||
| })), | ||
| get: mock(() => null), | ||
| all: mock(() => []), | ||
| })), | ||
| })), |
There was a problem hiding this comment.
Mock may be incomplete: missing orderBy() chain.
The localDb.select().from().orderBy() chain is used in some queries (e.g., workspaces.ts line 932), but the mock doesn't include orderBy. Tests using that pattern will fail.
🔎 Suggested fix
select: mock(() => ({
from: mock(() => ({
where: mock(() => ({
get: mock(() => null),
all: mock(() => []),
})),
+ orderBy: mock(() => ({
+ all: mock(() => []),
+ })),
get: mock(() => null),
all: mock(() => []),
})),
})),📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| mock.module("main/lib/local-db", () => ({ | |
| localDb: { | |
| select: mock(() => ({ | |
| from: mock(() => ({ | |
| where: mock(() => ({ | |
| get: mock(() => null), | |
| all: mock(() => []), | |
| })), | |
| get: mock(() => null), | |
| all: mock(() => []), | |
| })), | |
| })), | |
| mock.module("main/lib/local-db", () => ({ | |
| localDb: { | |
| select: mock(() => ({ | |
| from: mock(() => ({ | |
| where: mock(() => ({ | |
| get: mock(() => null), | |
| all: mock(() => []), | |
| })), | |
| orderBy: mock(() => ({ | |
| all: mock(() => []), | |
| })), | |
| get: mock(() => null), | |
| all: mock(() => []), | |
| })), |
🤖 Prompt for AI Agents
In apps/desktop/test-setup.ts around lines 128 to 139, the localDb mock defines
select().from().where().get/all and select().from().get/all but is missing an
orderBy() chain used by code (e.g., workspaces.ts line 932); update the mock to
include orderBy() on the same chain levels (i.e., have from() and its returned
object provide an orderBy method that returns an object exposing get and all,
and ensure any nested objects that represent query builders also expose orderBy
chaining) so tests using select().from().orderBy().get/all succeed.
better-sqlite3 uses the `bindings` npm package to locate its native .node file at runtime. This package (and its dependency file-uri-to-path) were not being included in the electron-builder output, causing the app to crash on startup with "Cannot find module 'bindings'" error. Changes: - Add bindings and file-uri-to-path to electron-builder files section - Add both packages to asarUnpack for proper path resolution - Update copy-native-modules.ts to also handle these dependencies 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Bumps desktop app version to 0.0.34.
This PR was automatically created by the release script.
Summary by CodeRabbit
Release Notes
✏️ Tip: You can customize this high-level summary in your review settings.