-
Notifications
You must be signed in to change notification settings - Fork 0
chore(electron): remove old .cjs files and migrate dev-runner to TypeScript #15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…Script - Remove all old .cjs files that were replaced by TypeScript versions in PR #13 - Migrate dev-runner.cjs to dev-runner.ts - Update WindowManager.ts to use correct preload paths for built files - Update test files to reference .ts files instead of .cjs - Update scripts/dev.js to use tsx for running dev-runner.ts All Electron code is now fully TypeScript.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Caution Review failedThe pull request is closed. 📝 WalkthroughWalkthroughThis PR removes many legacy CommonJS Electron modules and preload scripts, migrates core pieces to TypeScript and ESM, updates build/lazy-load outputs to preserve per-module artifacts, and adds a Settings window API with new preload and IPC handlers for settings (open/close and start-at-login / dock/menu visibility toggles). Changes
Sequence Diagram(s)sequenceDiagram
participant Renderer
participant Preload
participant Main
participant WindowManager
Renderer->>Preload: call electronAPI.settings.setStartAtLogin(true) / setHideAppIcon(false) / settings.open()
Preload->>Main: ipcRenderer.invoke('settings:setStartAtLogin' / 'settings:setHideAppIcon' / 'settings:open', payload)
Main->>WindowManager: createSettingsWindow() or openSettings()
WindowManager-->>Main: settings window created / focused
Main-->>Preload: return result (boolean / success)
Preload-->>Renderer: Promise resolves with result
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 📜 Recent review detailsConfiguration used: defaults Review profile: CHILL Plan: Pro 📒 Files selected for processing (6)
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 |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #15 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 2 2
Lines 9 9
Branches 2 2
=========================================
Hits 9 9 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
The latest updates on your projects. Learn more about Argos notifications ↗︎
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (4)
electron/__tests__/icon-system.test.mjs (2)
76-123: Consider dropping the explicit.tsextension + add module/global cleanup to avoid brittle test coupling.
Right now this relies on the test runner being able to import TypeScript directly from an ESM.mjstest file, and theglobal.nativeImage/electronmocks can leak across tests.Proposed patch (more portable import + cleanup)
@@ beforeEach(async () => { + vi.resetModules() // Mock Electron modules vi.doMock('electron', () => ({ @@ - // Mock the global nativeImage for the SystemTrayManager - global.nativeImage = { + // Mock the global nativeImage for the SystemTrayManager + const prevNativeImage = globalThis.nativeImage + globalThis.nativeImage = { createFromPath: vi.fn(() => ({ isEmpty: vi.fn(() => false), resize: vi.fn(() => ({})), })), } @@ // Import after mocking - const SystemTrayManagerModule = await import('../SystemTrayManager.ts') + const SystemTrayManagerModule = await import('../SystemTrayManager') SystemTrayManager = SystemTrayManagerModule.default @@ trayManager = new SystemTrayManager(mockWindowManager) + + // stash for afterEach restore (or use a closure var above) + trayManager.__prevNativeImage = prevNativeImage }) afterEach(() => { if (trayManager) { trayManager.destroy() } + // restore global mutation + mocks + globalThis.nativeImage = trayManager?.__prevNativeImage + vi.unmock('electron') })To verify runner compatibility, please confirm
vitest.config.electron.ts(or equivalent) is set up to transform TS for.mjstests and resolves../SystemTrayManageras intended.
150-173: ESM portability:require('fs')and__filenameare not guaranteed in a.mjstest.
Even if Vitest currently makes this work, it’s an easy future break (Node ESM doesn’t definerequire/__filenameby default).Proposed patch (use ESM-safe equivalents)
@@ import fs from 'fs' import path from 'path' +import { createRequire } from 'module' +import { fileURLToPath } from 'url' @@ describe('Icon System', () => { + const require = createRequire(import.meta.url) + const __filename = fileURLToPath(import.meta.url) @@ it('should handle errors gracefully', () => { // Mock fs.existsSync to throw an error - const originalExistsSync = require('fs').existsSync - require('fs').existsSync = vi.fn(() => { + const originalExistsSync = fs.existsSync + fs.existsSync = vi.fn(() => { throw new Error('Test error') }) @@ // Restore original function - require('fs').existsSync = originalExistsSync + fs.existsSync = originalExistsSync })Please verify your current Vitest runtime mode for Electron tests (Node ESM vs transformed) so this file won’t regress on runner upgrades.
electron/__tests__/deep-link-manager.test.mjs (2)
83-86: Update outdated comments to reflect ES module imports.The comments reference CommonJS module behavior, but the code now imports a TypeScript file that likely uses ES module syntax. The comments should be updated to reflect the current module system.
📝 Suggested comment update
- // Import DeepLinkManager using dynamic ESM import (works with CommonJS modules) - // CommonJS module.exports becomes .default in ESM + // Import DeepLinkManager using dynamic ESM import with cache busting + // Access the default export from the ES module const module = await import('../DeepLinkManager.ts?t=' + Date.now()) DeepLinkManager = module.default
108-108: Update file reference in comment.The comment references
main.cjs, but the PR migrated away from.cjsfiles. Consider updating the reference to reflect the current TypeScript file name.📝 Suggested comment update
- // Note: 'open-url' listener is registered in main.cjs BEFORE app.whenReady() + // Note: 'open-url' listener is registered in main.ts BEFORE app.whenReady()
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (25)
electron/AutoUpdater.cjselectron/ConfigManager.cjselectron/DeepLinkManager.cjselectron/IPCErrorHandler.cjselectron/LazyLoadManager.cjselectron/MemoryProfiler.cjselectron/MenuManager.cjselectron/NotificationManager.cjselectron/OAuthManager.cjselectron/ShortcutManager.cjselectron/SystemIntegrationErrorHandler.cjselectron/SystemTrayManager.cjselectron/WindowManager.cjselectron/WindowManager.tselectron/WindowStateManager.cjselectron/__tests__/deep-link-manager.test.mjselectron/__tests__/icon-system.test.mjselectron/auth-manager.cjselectron/dev-runner.tselectron/logger.cjselectron/main.cjselectron/performance-config.cjselectron/preload-floating.cjselectron/preload.cjsscripts/dev.js
💤 Files with no reviewable changes (20)
- electron/MemoryProfiler.cjs
- electron/WindowManager.cjs
- electron/MenuManager.cjs
- electron/ShortcutManager.cjs
- electron/SystemTrayManager.cjs
- electron/auth-manager.cjs
- electron/logger.cjs
- electron/LazyLoadManager.cjs
- electron/IPCErrorHandler.cjs
- electron/NotificationManager.cjs
- electron/performance-config.cjs
- electron/preload-floating.cjs
- electron/ConfigManager.cjs
- electron/AutoUpdater.cjs
- electron/WindowStateManager.cjs
- electron/OAuthManager.cjs
- electron/preload.cjs
- electron/main.cjs
- electron/SystemIntegrationErrorHandler.cjs
- electron/DeepLinkManager.cjs
🧰 Additional context used
🧬 Code graph analysis (2)
electron/WindowManager.ts (1)
scripts/dev.js (2)
__filename(8-8)__dirname(9-9)
electron/dev-runner.ts (2)
scripts/dev.js (2)
__filename(8-8)__dirname(9-9)src/types/utility.ts (1)
Error(31-34)
⏰ 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). (3)
- GitHub Check: build
- GitHub Check: e2e-web-tests
- GitHub Check: e2e-electron-tests
🔇 Additional comments (10)
electron/__tests__/deep-link-manager.test.mjs (1)
32-34: LGTM - Mock path correctly updated for TypeScript migration.The mock path has been properly updated from the CommonJS version to the TypeScript version, maintaining the same mock structure.
electron/dev-runner.ts (4)
28-36: LGTM!The ESM migration is correctly implemented. The import statements use proper ES module syntax, and the
__filename/__dirnamederivation pattern usingfileURLToPathis consistent with the pattern used inscripts/dev.js.
53-79: LGTM!The
checkServerfunction is well-typed and implements a clean retry mechanism. The inner functions have proper type annotations, and the promise-based approach correctly handles both success and failure cases.
102-114: LGTM!The path resolution for the main process and Electron binary is correct. Using
__dirname(derived from the TypeScript source location) with relative path navigation will correctly resolve todist-electron/main/index.cjsat the project root level when running viatsx.
134-138: LGTM!Good error handling pattern. The
instanceof Errorcheck properly handles TypeScript'sunknowncatch clause type, andString(error)provides a reasonable fallback for non-Error values.scripts/dev.js (1)
123-136: LGTM!The change correctly invokes the TypeScript dev-runner via
tsx. The path construction usingpath.joinis appropriate for cross-platform compatibility. Thetsxdependency is available (v4.21.0) and thedev-runner.tsfile exists at the expected path.electron/WindowManager.ts (4)
18-20: LGTM! Correct ES module imports.The addition of
fileURLToPathandappimports are necessary and correct for ES module path resolution and runtime preload path detection.
26-28: LGTM! Standard ES module pattern.The ES module path resolution pattern is correct and consistent with the pattern used in
scripts/dev.js.
240-256: LGTM! Consistent with main window preload path.The floating navigator preload path resolution follows the same pattern as the main window (lines 125-135), maintaining consistency. The same verification considerations mentioned in the previous comment apply here.
125-135: Path resolution is correct and properly configured.The preload path resolution correctly accounts for the electron-vite build structure. The
__dirnamevariable resolves todist-electron/mainat runtime (where the compiled main process runs), making the development path__dirname/../dist-electron/preload/preload.cjsresolve todist-electron/preload/preload.cjs, which exactly matches the electron-vite preload configuration. The packaged path usingprocess.resourcesPathfollows standard Electron conventions. The consistent use of this pattern for the floating window preload and the icon path further confirms the setup is correct.
- Add createSettingsWindow, openSettings, closeSettings methods to WindowManager - Add settings:open, settings:close IPC handlers to main.ts - Add settings:setHideAppIcon IPC handler for dock visibility control - Add settings:setShowInMenuBar IPC handler (placeholder) - Add settings:setStartAtLogin and settings:getLoginItemSettings IPC handlers - Update MenuManager.openPreferences() to use windowManager.openSettings() These features were lost during the TypeScript migration in PR #13. All Settings functionality from PR #14 is now restored.
- Add .github/coderabbit.yml with project-specific settings - Configure review profile for Next.js + Electron + TypeScript project - Set up path filters for Electron, Prisma, and test files - Configure auto-review with appropriate include/exclude paths - Add language-specific focus areas for TypeScript, JavaScript, and Prisma - Set PR size limits and commit message review settings
- Fix import.meta.url error in WindowManager.ts with @ts-ignore - Prefix unused variables with _ and add @ts-ignore comments: - NotificationManager: _fallbackMode - MenuManager: _configManager - ShortcutManager: _globalShortcuts - SystemIntegrationErrorHandler: _userNotified - Fix ESLint console.log errors in scripts/dev.js - All TypeScript type checks now pass
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
electron/dev-runner.ts (1)
108-120: Critical: Windows compatibility issue with Electron spawn.The hardcoded path to
node_modules/.bin/electronwill fail on Windows, where npm/pnpm create.cmdwrapper scripts. The spawn call will throw an ENOENT error, preventing the dev server from starting on Windows.🔧 Proposed fix for cross-platform compatibility
Solution 1 (Recommended): Use 'electron' directly and let Node.js resolve it
- const electronProcess: ChildProcess = spawn( - path.join(process.cwd(), 'node_modules', '.bin', 'electron'), - [mainProcessPath], + const electronProcess: ChildProcess = spawn('electron', [mainProcessPath], { - { - stdio: 'inherit', + stdio: 'inherit', - env: { + env: {Solution 2: Add platform-specific extension
+ const electronBin = path.join( + process.cwd(), + 'node_modules', + '.bin', + process.platform === 'win32' ? 'electron.cmd' : 'electron', + ) + const electronProcess: ChildProcess = spawn( - path.join(process.cwd(), 'node_modules', '.bin', 'electron'), + electronBin, [mainProcessPath],
🤖 Fix all issues with AI agents
In @electron/SystemTrayManager.ts:
- Around line 441-458: The tray "Settings" click handler currently restores the
window and navigates via mainWindow.webContents.executeJavaScript("/settings");
change it to call this.windowManager.openSettings() for consistency with
MenuManager; keep the initial this.windowManager.restoreFromTray() call and
remove the getMainWindow/executeJavaScript block, and ensure the catch still
logs errors (log.error) if openSettings() throws.
🧹 Nitpick comments (6)
electron/NotificationManager.ts (1)
120-122: Remove dead code or implement proper usage.The
_fallbackModefield is assigned in four locations (lines 303, 311, 322, 331) but never read anywhere. Using@ts-ignoreto suppress the unused variable warning is a code smell that hides legitimate TypeScript feedback.Consider one of these approaches:
- Remove it entirely if it serves no current purpose
- Log the fallback mode in each error handler instead of storing it
- Actually use it by exposing it via a getter or including it in error reports
- If keeping for future use, use
@ts-expect-errorinstead of@ts-ignore(will error if the code becomes valid)♻️ Option 1: Remove the unused field
- /** Fallback mode - stored for debugging/future use */ - // @ts-ignore - Intentionally unused, stored for debugging - private _fallbackMode: string | null = null - /** Fallback methods */ private fallbackMethods: FallbackMethods | null = nullThen remove all assignments at lines 303, 311, 322, 331:
private handleNotificationUnavailable(_reason: string): void { this.preferences.enabled = false - this._fallbackMode = 'unavailable' }(repeat for other handlers)
♻️ Option 2: Log instead of storing
- /** Fallback mode - stored for debugging/future use */ - // @ts-ignore - Intentionally unused, stored for debugging - private _fallbackMode: string | null = null - /** Fallback methods */private handleNotificationUnavailable(_reason: string): void { this.preferences.enabled = false - this._fallbackMode = 'unavailable' + log.debug('Notification fallback mode: unavailable') }(repeat for other handlers)
electron/ShortcutManager.ts (1)
89-91: Consider removing unused field or deferring to future PR.The
_globalShortcutsfield is initialized but never referenced elsewhere in the codebase. While the comment indicates it's "stored for future features," including unused code with a@ts-ignoredirective adds maintenance burden without immediate value. Consider either:
- Removing it entirely and re-introducing when the feature is implemented
- Using an ESLint disable comment instead of
@ts-ignorefor better IDE tooling support♻️ Option 1: Remove unused field
- /** Global shortcuts (always active) - stored for future use */ - // @ts-ignore - Intentionally unused, stored for future features - private _globalShortcuts: Set<string>this.contextualShortcuts = new Set([ 'newTask', 'minimize', 'toggleAlwaysOnTop', 'focusFloatingNavigator', ]) - this._globalShortcuts = new Set(['showMainWindow']) this.focusListenersSetup = false♻️ Option 2: Use ESLint disable if preservation is required
- /** Global shortcuts (always active) - stored for future use */ - // @ts-ignore - Intentionally unused, stored for future features - private _globalShortcuts: Set<string> + /** Global shortcuts (always active) - stored for future use */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars + private _globalShortcuts: Set<string>electron/WindowManager.ts (1)
268-271: Consider extracting preload path resolution into a helper function.The preload path resolution logic at lines 268-271 (for floating window) duplicates the pattern from lines 135-137 (for main window) and lines 485-487 (for settings window). While not critical, extracting this into a reusable helper would improve maintainability:
private resolvePreloadPath(preloadFileName: string): string { return app.isPackaged ? path.join(process.resourcesPath, 'preload', preloadFileName) : path.join(__dirname, '..', 'preload', preloadFileName) }Then use:
const preloadPath = this.resolvePreloadPath('preload.cjs')electron/MenuManager.ts (1)
47-49: Consider whether _configManager reference is needed.The
_configManagerfield is stored with a@ts-ignoredirective indicating it's "intentionally unused, stored for future features" (lines 47-49). While this pattern is acceptable for planned features, storing unused references can:
- Increase memory footprint unnecessarily
- Create confusion about actual dependencies
- Risk becoming stale if the planned feature never materializes
If the future feature is imminent, this is fine. Otherwise, consider removing it until actually needed.
Also applies to: 57-57, 81-81, 704-704
electron/main.ts (1)
1541-1569: LGTM: settings:setShowInMenuBar is appropriately stubbed.This placeholder handler correctly validates input, logs that the feature isn't implemented yet, and returns
falseto indicate unavailability. The TODO comment (line 1559) clearly documents the next implementation step.Would you like me to generate an implementation for the menu bar visibility feature using SystemTrayManager, or open an issue to track this task?
electron/dev-runner.ts (1)
100-105: The pathdist-electron/main/index.cjsis correct and theprocess.cwd()approach is safe in this context.The electron-vite configuration confirms this output structure:
outDir: 'dist-electron/main'withformat: 'cjs'andentryFileNames: '[name].cjs'(electron.vite.config.ts:50, 42-43). The assumption about running from the project root is documented in the code (line 99) and enforced by the execution flow—dev-runner.ts is only invoked fromscripts/dev.js, which spawns it from the project root.That said, for consistency and defensive coding, consider using
import.meta.url(as already done in scripts/dev.js lines 6-9) to make the path resolution more robust and independent of the working directory:import { fileURLToPath } from 'url' const __dirname = path.dirname(fileURLToPath(import.meta.url)) const mainProcessPath = path.join(__dirname, '..', 'dist-electron', 'main', 'index.cjs')
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (14)
.github/coderabbit.ymlbuild/icons/icon-manifest.jsonelectron.vite.config.tselectron/LazyLoadManager.tselectron/MenuManager.tselectron/NotificationManager.tselectron/ShortcutManager.tselectron/SystemIntegrationErrorHandler.tselectron/SystemTrayManager.tselectron/WindowManager.tselectron/dev-runner.tselectron/main.tselectron/preload.tsscripts/dev.js
✅ Files skipped from review due to trivial changes (2)
- build/icons/icon-manifest.json
- .github/coderabbit.yml
🧰 Additional context used
🧬 Code graph analysis (5)
electron/dev-runner.ts (2)
scripts/dev.js (1)
electronProcess(26-26)src/types/utility.ts (1)
Error(31-34)
electron/SystemTrayManager.ts (2)
electron/__tests__/icon-system.test.mjs (1)
iconDir(7-7)scripts/dev.js (1)
__dirname(9-9)
electron/preload.ts (1)
src/types/utility.ts (1)
Error(31-34)
electron/WindowManager.ts (2)
scripts/dev.js (2)
__filename(8-8)__dirname(9-9)electron/__tests__/WindowManager.test.mjs (1)
baseUrl(202-202)
electron/MenuManager.ts (1)
electron/ConfigManager.ts (1)
ConfigManager(194-816)
⏰ 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). (3)
- GitHub Check: build
- GitHub Check: e2e-web-tests
- GitHub Check: e2e-electron-tests
🔇 Additional comments (21)
electron.vite.config.ts (1)
23-47: LGTM! Build configuration correctly supports lazy loading.The addition of separate entry points with
preserveModules: truecreates the proper output structure for lazy loading viarequire(). The configuration aligns perfectly with the loading patterns inLazyLoadManager.tsand enables efficient on-demand module loading.electron/LazyLoadManager.ts (1)
104-156: LGTM! Lazy loading pattern correctly adapted for CommonJS output.The migration from dynamic imports to
require()with.cjspaths aligns with theelectron-vitebuild output structure. The fallback patternmod.NamedExport || mod.defaulthandles both named and default exports gracefully, and the updated comments clearly explain the module resolution strategy.scripts/dev.js (2)
89-113: LGTM! Build-first workflow correctly supports lazy loading.The addition of the pre-build step ensures that all
.cjsmodules are available before Electron starts, which is essential for the lazy loading mechanism introduced in this PR. The error handling properly rejects on non-zero exit codes.
150-163: LGTM! Electron startup correctly uses tsx for TypeScript dev-runner.The migration from running a
.cjsfile to usingtsxto executedev-runner.tsaligns with the TypeScript migration objectives. The environment variables and remote debugging configuration are preserved.electron/preload.ts (2)
1600-1652: LGTM! Settings API follows established patterns.The new settings API surface maintains consistency with existing APIs:
- Boolean input validation
- Sanitized IPC invocation via whitelisted channels
- Graceful error handling with logged errors and false returns
The comment on line 1619 noting "not yet implemented" for
setShowInMenuBaris appropriate documentation of current limitations.
137-140: All three settings channels are properly whitelisted with corresponding IPC handlers implemented.The three new IPC channels for settings operations are correctly added to the
ALLOWED_CHANNELSwhitelist, and all corresponding handlers exist in the main process:
'settings:setHideAppIcon': Fully implemented with macOS platform check and input validation'settings:setShowInMenuBar': Handler implemented with TODO for feature completion'settings:setStartAtLogin': Fully implemented with input validation and error handlingAll handlers include proper type validation and comprehensive error logging, maintaining the security-first approach of the preload script.
electron/WindowManager.ts (4)
26-29: LGTM: Standard ES module __dirname resolution.The
@ts-ignoredirective is acceptable here sinceimport.meta.urlis valid at runtime when processed by electron-vite, even though TypeScript's static analysis doesn't recognize it in this context. This pattern matches the approach inscripts/dev.js.
476-536: LGTM: Settings window creation follows secure patterns.The
createSettingsWindow()method correctly implements:
- Early return with focus if window already exists (lines 477-480)
- Security-first BrowserWindow configuration (nodeIntegration: false, contextIsolation: true)
- Ready-to-show pattern to prevent visual flash (lines 522-527)
- Proper cleanup via closed event handler (lines 530-533)
- Parent window relationship without blocking interaction (modal: false)
538-575: LGTM: Settings window lifecycle methods are well-implemented.The lifecycle methods (
openSettings,closeSettings,getSettingsWindow,hasSettingsWindow) follow consistent patterns with existing window management methods and include proper destroyed-state checks before operations.
583-585: LGTM: Settings window cleanup properly integrated.The cleanup method correctly includes settings window closure with appropriate null and destroyed-state checks, maintaining consistency with the existing window cleanup pattern.
electron/SystemTrayManager.ts (1)
335-337: LGTM: Icon path updated for new build structure.The path resolution correctly accounts for the TypeScript build output structure where
__dirnameis nowdist-electron/main/, requiring two levels up to reach the project root instead of one.electron/MenuManager.ts (1)
524-542: LGTM: openPreferences properly uses Settings window with fallback.The method correctly prioritizes
windowManager.openSettings()for a consistent settings experience, with appropriate fallback to IPC messaging when the window manager isn't available. The debug logging aids troubleshooting.electron/SystemIntegrationErrorHandler.ts (1)
114-116: LGTM: _userNotified follows established pattern for future features.Similar to
_configManagerin MenuManager, this field is stored for future notification tracking functionality. The@ts-ignoredirective and comment clearly indicate the intention.Also applies to: 146-146
electron/main.ts (5)
1475-1487: LGTM: settings:open handler properly manages Settings window.The handler correctly checks for
windowManageravailability, includes error handling with logging, and returns a boolean success indicator. Theasynckeyword is unnecessary sinceopenSettings()is synchronous, but it doesn't cause issues.
1489-1501: LGTM: settings:close handler mirrors settings:open pattern.Follows the same robust pattern as
settings:openwith proper null checks and error handling.
1503-1539: LGTM: settings:setHideAppIcon correctly handles macOS dock visibility.The handler properly:
- Checks platform (darwin-only API, lines 1509-1511)
- Validates input type (lines 1515-1520)
- Uses correct activation policies ('accessory' to hide, 'regular' to show)
- Includes error handling and logging
- Returns success for no-op on non-macOS platforms
1571-1598: LGTM: settings:setStartAtLogin correctly configures login behavior.The handler properly validates input, uses the correct Electron API (
app.setLoginItemSettings), and setsopenAsHidden: falsefor normal startup visibility. The API is cross-platform compatible (macOS, Windows, Linux).
1600-1611: LGTM: settings:getLoginItemSettings provides proper error fallback.The handler correctly retrieves login item settings with appropriate error handling and a sensible default return value.
electron/dev-runner.ts (3)
28-32: LGTM! Clean ES module migration.The import statements correctly migrate from CommonJS to ES modules with appropriate type imports for ChildProcess. The logger import aligns with the broader TypeScript migration across the Electron codebase.
49-75: LGTM! Well-typed server check logic.The type annotations strengthen the function signature and internal callbacks. The retry logic with 1-second intervals and configurable retry count is appropriate for waiting on Next.js compilation.
131-132: LGTM! Improved error handling.The type-safe error message extraction correctly handles both
Errorinstances and other thrown values, preventing potential runtime errors from assuming all caught values areErrorobjects.
- Replace executeJavaScript navigation with windowManager.openSettings() - Maintains restoreFromTray() call for window restoration - Removes low-level getMainWindow/executeJavaScript logic - Keeps error handling with log.error() if openSettings() throws - Aligns with MenuManager.openPreferences() pattern
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
electron/WindowManager.ts (1)
461-464: Consider extracting preload path resolution to a helper method.The preload path resolution logic is duplicated in three places:
createMainWindow,createFloatingNavigator, andcreateSettingsWindow. Consider extracting to a private helper method:♻️ Suggested refactor
+ /** + * Resolves the path to a preload script, handling both packaged and development environments. + */ + private getPreloadPath(scriptName: string): string { + return app.isPackaged + ? path.join(process.resourcesPath, 'preload', scriptName) + : path.join(__dirname, '..', 'preload', scriptName) + } createMainWindow(): BrowserWindow { // ... - const preloadPath = app.isPackaged - ? path.join(process.resourcesPath, 'preload', 'preload.cjs') - : path.join(__dirname, '..', 'preload', 'preload.cjs') + const preloadPath = this.getPreloadPath('preload.cjs')Apply similarly to
createFloatingNavigatorandcreateSettingsWindow.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
electron/WindowManager.ts
🧰 Additional context used
🧬 Code graph analysis (1)
electron/WindowManager.ts (2)
scripts/dev.js (2)
__filename(8-8)__dirname(9-9)electron/__tests__/WindowManager.test.mjs (1)
baseUrl(202-202)
⏰ 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). (4)
- GitHub Check: build
- GitHub Check: e2e-web-tests
- GitHub Check: e2e-electron-tests
- GitHub Check: storybook-test
🔇 Additional comments (6)
electron/WindowManager.ts (6)
26-29: LGTM! Standard ES module __dirname resolution.The pattern matches the approach used in
scripts/dev.jsand is the correct way to resolve__dirnamein ES modules. The@ts-ignorecomment appropriately documents that electron-vite handlesimport.meta.urlat runtime.
63-65: LGTM!The
settingsWindowproperty follows the same pattern asmainWindowandfloatingNavigator, maintaining consistency in the window management approach.
245-249: Consistent preload resolution pattern.Same observation as the main window preload path—verify that
process.resourcesPath/preload/preload-floating.cjsis the correct location in packaged builds. The pattern is consistent with the main window, which is good for maintainability.
519-538: LGTM! Clean settings window lifecycle management.The implementation correctly handles:
- Focusing existing window vs. creating new one in
openSettings- Delegating null cleanup to the 'closed' event handler in
closeSettings(good comment explaining this)- Proper
isDestroyed()checks to prevent operations on destroyed windows
560-562: LGTM!Settings window cleanup is properly integrated into the
cleanup()method, following the same pattern as other windows and respecting the parent-child relationship by closing before the main window.
130-134: The preload path resolution is correct for your build configuration.The electron-vite config outputs the preload to
dist-electron/preload/preload.cjs, which electron-builder includes as part of the packaged app. On macOS,process.resourcesPathpoints to the Resources directory where these files are extracted, makingpath.join(process.resourcesPath, 'preload', 'preload.cjs')the correct packaged path. The development path is also correct since__dirnameresolves todist-electron/main, so../ + preload/preload.cjspoints to the correct location.Likely an incorrect or invalid review comment.
…AutoUpdater - Simplified preload script path resolution by removing reliance on app.isPackaged. - Added detailed comments to clarify the behavior of preload paths in both development and production environments. - Updated AutoUpdater to use a custom logger interface instead of electron-log for better control over logging output.
- Improved error handling in checkServer function to provide more informative rejection messages. - Added graceful shutdown handling for Electron processes, including cleanup of event listeners and processes. - Updated dev.js to ensure proper cleanup of build processes and prevent memory leaks. - Enhanced logging in AutoUpdater to utilize a custom logger interface for better control over log output.
….yaml - Deleted electron-log from dependencies in package.json. - Updated pnpm-lock.yaml to reflect the removal of electron-log, cleaning up unused entries.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In @electron/AutoUpdater.ts:
- Around line 65-74: The custom UpdaterLogger type uses rest parameters which
mismatches electron-updater's Logger signature and forces unsafe casts; replace
the custom interface by importing and using electron-updater's Logger type,
change the updaterLogger object to implement Logger (methods like info(message?:
any): void, warn(...), error(...), debug(...)) and remove the (log.* as
LogMethod) and final cast to autoUpdater.logger so you assign updaterLogger
directly to autoUpdater.logger; ensure each method forwards a single optional
message to your existing log methods (e.g., log.info(message || '')).
🧹 Nitpick comments (2)
scripts/dev.js (1)
138-143: Empty callback in stdout handler.The
nextProcess.stdout.on('data', ...)callback has an empty conditional block. Either log the readiness message or remove the unused handler.♻️ Suggested fix
// Handle Next.js output nextProcess.stdout.on('data', (data) => { const output = data.toString() if (output.includes('Ready') || output.includes('compiled')) { + // eslint-disable-next-line no-console + console.log(`📦 Next.js: ${output.trim()}`) } })Or if logging is not desired, remove the conditional entirely:
// Handle Next.js output - nextProcess.stdout.on('data', (data) => { - const output = data.toString() - if (output.includes('Ready') || output.includes('compiled')) { - } - }) + // Pipe stdout to console if needed + nextProcess.stdout.pipe(process.stdout)electron/dev-runner.ts (1)
120-132: Consider usingrequire.resolvefor more robust Electron binary resolution.Using a hardcoded path to
node_modules/.bin/electronmay break with different package managers (pnpm hoisting, monorepos) or when the binary name differs on Windows (.cmdextension).♻️ Suggested improvement
+import { createRequire } from 'module' + +const require = createRequire(import.meta.url) - const electronProcess: ChildProcess = spawn( - path.join(process.cwd(), 'node_modules', '.bin', 'electron'), - [mainProcessPath], + // Resolve electron binary path reliably across package managers + const electronPath = require.resolve('electron/cli.js') + + const electronProcess: ChildProcess = spawn( + process.execPath, // Node.js + [electronPath, mainProcessPath], { stdio: 'inherit',Alternatively, use
electronfromelectronpackage directly:import electron from 'electron' const electronProcess = spawn(electron as unknown as string, [mainProcessPath], { ... })
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
.github/coderabbit.ymlelectron/AutoUpdater.tselectron/WindowManager.tselectron/dev-runner.tsscripts/dev.js
🚧 Files skipped from review as they are similar to previous changes (1)
- .github/coderabbit.yml
🧰 Additional context used
🧬 Code graph analysis (2)
electron/dev-runner.ts (1)
scripts/dev.js (1)
electronProcess(26-26)
scripts/dev.js (1)
scripts/generate-icons.js (1)
__dirname(15-15)
⏰ 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). (3)
- GitHub Check: build
- GitHub Check: e2e-electron-tests
- GitHub Check: e2e-web-tests
🔇 Additional comments (19)
electron/WindowManager.ts (6)
26-29: LGTM! Standard ESM__dirnameresolution pattern.The
@ts-ignoreis appropriate here sinceimport.meta.urlis valid at runtime with electron-vite, and the comment clearly explains the rationale.
63-65: LGTM!The new
settingsWindowfield follows the established pattern used formainWindowandfloatingNavigator.
130-142: Excellent documentation on preload path resolution.The detailed comments clearly explain the dev vs. production path semantics and why
process.resourcesPathisn't used. This prevents a common Electron packaging pitfall where preload scripts fail to load in production builds.
253-260: LGTM!Consistent preload path resolution with appropriate cross-reference to the main documentation in
createMainWindow().
460-524: Well-structured settings window implementation.The security configuration (
nodeIntegration: false,contextIsolation: true,webSecurity: true) is consistent with other windows. The lifecycle management with theready-to-showevent andclosedcleanup handler follows established patterns.Minor observation: the early-return guard in
createSettingsWindow()(lines 466-469) duplicates the check inopenSettings()(line 531). This is acceptable defensive coding for whencreateSettingsWindow()is called directly.
568-582: LGTM!Proper cleanup order: settings window (child) is closed before the main window (parent), preventing potential issues with parent-child window relationships.
scripts/dev.js (4)
14-23: LGTM!The updated documentation accurately reflects the new workflow: building Electron code first, then starting Next.js, waiting for readiness, and finally launching Electron.
27-27: LGTM!Good addition of
buildProcesstracking with proper cleanup in the shutdown path. The cleanup correctly kills the build process and nullifies the reference before handling other processes.Also applies to: 31-35
95-124: LGTM with minor observation.The build step implementation is solid:
- Proper environment setup with
NODE_ENV=development- Correctly awaits build completion before proceeding
- Clears
buildProcessreference on completion or error- Distinguishes between exit code 0, null (signal-based termination), and non-zero failures
One thing to note: if the build is killed via
cleanup()during shutdown,codewill benull, which is correctly handled by thecode !== nullcheck to avoid false error reporting.
161-163: LGTM!Good migration to use
pnpm tsxfor running the TypeScript dev-runner directly. Usingpath.join(__dirname, '..', 'electron', 'dev-runner.ts')correctly resolves the path relative to the script's location, consistent with the__dirnamepattern used in other scripts likegenerate-icons.js.electron/dev-runner.ts (6)
28-32: LGTM!Clean ES module imports with proper TypeScript type imports (
type ChildProcess). The logger import path correctly references the migrated./loggermodule (without.cjsextension).
49-87: LGTM!Solid implementation of
checkServer:
- Properly typed with
Promise<void>return typeres.resume()correctly consumes the response stream to avoid socket leakslastErrortracking provides meaningful error messages on final failure- Non-200 responses are now properly handled as errors
134-165: LGTM!Excellent signal handling implementation:
- Named handlers (
handleSignal) allow proper cleanup viaremoveListenercleanup()removes all listeners to prevent memory leaks and duplicate handling- 3-second grace period before force exit is reasonable for graceful shutdown
- Both SIGINT and SIGTERM are handled consistently
163-172: LGTM!Proper process exit handling:
cleanup()is called before exit to remove listeners- Nullish coalescing (
code ?? 0) correctly handlesnullcode from signal-based termination- Error case logs details and exits with code 1
173-178: LGTM!Good defensive error handling with proper type narrowing for the error message extraction.
110-117: The pathdist-electron/main/index.cjsis correctly aligned with theelectron.vite.config.tsbuild configuration. The configuration explicitly setsoutDir: 'dist-electron/main'for the main process, withentryFileNames: '[name].cjs'mapping theindexentry point toindex.cjs.electron/AutoUpdater.ts (3)
26-35: LGTM! Well-defined logger interface.The
UpdaterLoggerinterface is cleanly defined with appropriate rest-parameter signatures. The comment clearly explains the rationale for using a custom logger wrapper instead ofelectron-logat runtime.
101-101: LGTM! Improved log message formatting.Removing the trailing colons from these log messages aligns with structured logging best practices, where the message and data object are cleanly separated. This makes the logs more readable and easier to parse.
Also applies to: 110-110, 136-136
14-14: Logger module is correctly set up and compatible.The
./loggermodule exists atelectron/logger.tsand properly exports thelogobject with all required methods (info,warn,error,debug). The signatures are compatible with usage throughout AutoUpdater.ts.
- Modified .gitignore to include new build output directories: dist and dist-electron-dev. - Updated package.json clean script to remove dist and dist-electron directories. - Adjusted build-and-release workflow to reference the new dist directory for macOS application outputs. - Revised README and BUILD_AND_DEPLOYMENT documentation to reflect changes in output directory from dist-electron to dist.
Summary
This PR completes the TypeScript migration started in PR #13 by:
Changes
Testing
vite v7.3.1 building ssr environment for production...
transforming...
✓ 9 modules transformed.
rendering chunks...
dist-electron/main/index.cjs 117.51 kB │ map: 255.42 kB
✓ built in 131ms
vite v7.3.1 building ssr environment for production...
transforming...
✓ 3 modules transformed.
rendering chunks...
dist-electron/preload/chunks/logger-2Rw6nBsz.cjs 2.23 kB │ map: 6.29 kB
dist-electron/preload/preload-floating.cjs 6.04 kB │ map: 12.83 kB
dist-electron/preload/preload.cjs 44.48 kB │ map: 77.83 kB
✓ built in 25ms succeeds
RUN v4.0.16 /Users/ryotamurakami/corelive
✓ |electron| electron/tests/floating-navigator-integration.test.mjs (22 tests) 7ms
✓ |electron| electron/tests/WindowManager.test.mjs (32 tests) 9ms
{"level":"error","time":"2026-01-11T13:04:35.818Z","pid":94133,"hostname":"Ryotas-MacBook-Pro.local","msg":"Attempted to listen to unauthorized channel: malicious-channel"}
{"level":40,"time":1768136675819,"pid":94130,"hostname":"Ryotas-MacBook-Pro.local","component":"corelive","msg":"Cannot set tray icon state: tray not available"}
{"level":40,"time":1768136675820,"pid":94130,"hostname":"Ryotas-MacBook-Pro.local","component":"corelive","msg":"Cannot set tray icon state: tray not available"}
{"level":"error","time":"2026-01-11T13:04:35.818Z","pid":94133,"hostname":"Ryotas-MacBook-Pro.local","msg":"Attempted to listen to unauthorized channel: file-system-event"}
{"level":"error","time":"2026-01-11T13:04:35.818Z","pid":94133,"hostname":"Ryotas-MacBook-Pro.local","msg":"Callback must be a function"}
{"level":"error","time":"2026-01-11T13:04:35.818Z","pid":94133,"hostname":"Ryotas-MacBook-Pro.local","msg":"Callback must be a function"}
✓ |electron| electron/tests/preload-security.test.mjs (15 tests) 5ms
{"level":50,"time":1768136675820,"pid":94130,"hostname":"Ryotas-MacBook-Pro.local","component":"corelive","context":{},"msg":"Failed to set tray icon state:"}
✓ |electron| electron/tests/icon-system.test.mjs (26 tests) 34ms
✓ |electron| electron/tests/deep-link-manager.test.mjs (19 tests) 35ms
{"level":"warn","time":"2026-01-11T13:04:36.120Z","pid":94128,"hostname":"Ryotas-MacBook-Pro.local","msg":"Handler failed, using degraded mode: Handler failed"}
✓ |electron| electron/tests/main-process.test.mjs (12 tests) 307ms
✓ should handle IPC errors with retry logic 301ms
Test Files 6 passed (6)
Tests 126 passed (126)
Start at 22:04:35
Duration 464ms (transform 355ms, setup 0ms, import 407ms, tests 396ms, environment 0ms) passes
All Electron code is now fully TypeScript.
Summary by CodeRabbit
Removed Features
New Features
Build/Development
✏️ Tip: You can customize this high-level summary in your review settings.