11import { BrowserWindow , app } from 'electron'
2- import { autoUpdater , UpdateInfo } from 'electron-updater '
3- import type { ProgressInfo } from 'electron-updater'
2+ import { createRequire } from 'node:module '
3+ import type { ProgressInfo , UpdateInfo as ElectronUpdateInfo } from 'electron-updater'
44import type { IpcResult } from '../../shared/types/ipc.types'
55import { read , write } from './persistence-service'
66
7+ // Lazy load electron-updater with error handling
8+ // This prevents app crash if electron-updater fails to load
9+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
10+ let autoUpdater : any = null
11+ let electronUpdaterLoaded = false
12+
13+ function getAutoUpdater ( ) {
14+ if ( ! electronUpdaterLoaded ) {
15+ try {
16+ const require = createRequire ( import . meta. url )
17+ const electronUpdater = require ( 'electron-updater' )
18+ autoUpdater = electronUpdater . autoUpdater
19+ electronUpdaterLoaded = true
20+ console . log ( 'electron-updater loaded successfully' )
21+ } catch ( error ) {
22+ console . error ( 'Failed to load electron-updater:' , error )
23+ autoUpdater = null
24+ electronUpdaterLoaded = true
25+ }
26+ }
27+ return autoUpdater
28+ }
29+
730// Updater error codes
831export const UpdaterErrorCodes = {
932 NOT_INITIALIZED : 'NOT_INITIALIZED' ,
@@ -42,7 +65,7 @@ export interface DownloadProgress {
4265// Full updater state
4366export interface UpdaterState {
4467 state : UpdateState
45- updateInfo : UpdateInfo | null
68+ updateInfo : ElectronUpdateInfo | null
4669 downloadProgress : DownloadProgress | null
4770 error : string | null
4871 skippedVersion : string | null
@@ -76,7 +99,7 @@ let updaterServiceInstance: UpdaterService | null = null
7699export class UpdaterService {
77100 private mainWindow : BrowserWindow | null = null
78101 private currentState : UpdateState = 'idle'
79- private currentUpdateInfo : UpdateInfo | null = null
102+ private currentUpdateInfo : ElectronUpdateInfo | null = null
80103 private currentDownloadProgress : DownloadProgress | null = null
81104 private currentError : string | null = null
82105 private skippedVersion : string | null = null
@@ -128,7 +151,7 @@ export class UpdaterService {
128151 /**
129152 * Check for updates manually
130153 */
131- async checkForUpdates ( ) : Promise < IpcResult < UpdateInfo > > {
154+ async checkForUpdates ( ) : Promise < IpcResult < ElectronUpdateInfo > > {
132155 if ( ! this . isInitialized ) {
133156 return {
134157 success : false ,
@@ -195,7 +218,11 @@ export class UpdaterService {
195218
196219 try {
197220 // Actually trigger the download with electron-updater
198- await autoUpdater . downloadUpdate ( )
221+ const updater = getAutoUpdater ( )
222+ if ( ! updater ) {
223+ throw new Error ( 'electron-updater not available' )
224+ }
225+ await updater . downloadUpdate ( )
199226 return { success : true , data : undefined }
200227 } catch ( error ) {
201228 this . isDownloading = false
@@ -236,7 +263,11 @@ export class UpdaterService {
236263 await this . performBackup ( )
237264
238265 // Set autoInstallOnAppQuit to trigger install on restart
239- autoUpdater . autoInstallOnAppQuit = true
266+ const updater = getAutoUpdater ( )
267+ if ( ! updater ) {
268+ throw new Error ( 'electron-updater not available' )
269+ }
270+ updater . autoInstallOnAppQuit = true
240271
241272 // Restart the app to apply update
242273 app . relaunch ( )
@@ -300,21 +331,27 @@ export class UpdaterService {
300331 * Setup electron-updater configuration and event handlers
301332 */
302333 private setupAutoUpdater ( ) : void {
334+ const updater = getAutoUpdater ( )
335+ if ( ! updater ) {
336+ console . warn ( 'electron-updater not available, auto-update will not work' )
337+ return
338+ }
339+
303340 // Configure for GitHub Releases
304- autoUpdater . setFeedURL ( {
341+ updater . setFeedURL ( {
305342 provider : 'github' ,
306343 owner : 'PecutAPP' ,
307344 repo : 'termul'
308345 } )
309346
310347 // Disable auto-download (we'll handle it manually)
311- autoUpdater . autoDownload = false
348+ updater . autoDownload = false
312349
313350 // Disable auto-install on quit (we'll control when to install)
314- autoUpdater . autoInstallOnAppQuit = false
351+ updater . autoInstallOnAppQuit = false
315352
316353 // Event handlers
317- autoUpdater . on ( 'update-available' , ( info : UpdateInfo ) => {
354+ updater . on ( 'update-available' , ( info : ElectronUpdateInfo ) => {
318355 console . log ( 'Update available:' , info . version )
319356 this . currentUpdateInfo = info
320357
@@ -336,12 +373,12 @@ export class UpdaterService {
336373 this . sendEvent ( 'update-available' , info )
337374 } )
338375
339- autoUpdater . on ( 'update-not-available' , ( info : UpdateInfo ) => {
376+ updater . on ( 'update-not-available' , ( info : ElectronUpdateInfo ) => {
340377 console . log ( 'Update not available, current version:' , info . version )
341378 this . setState ( 'idle' )
342379 } )
343380
344- autoUpdater . on ( 'download-progress' , ( progress : ProgressInfo ) => {
381+ updater . on ( 'download-progress' , ( progress : ProgressInfo ) => {
345382 this . currentDownloadProgress = {
346383 bytesPerSecond : progress . bytesPerSecond ,
347384 percent : progress . percent ,
@@ -351,15 +388,15 @@ export class UpdaterService {
351388 this . sendEvent ( 'download-progress' , this . currentDownloadProgress )
352389 } )
353390
354- autoUpdater . on ( 'update-downloaded' , ( info : UpdateInfo ) => {
391+ updater . on ( 'update-downloaded' , ( info : ElectronUpdateInfo ) => {
355392 console . log ( 'Update downloaded:' , info . version )
356393 this . isDownloading = false
357394 this . currentUpdateInfo = info
358395 this . setState ( 'downloaded' )
359396 this . sendEvent ( 'update-downloaded' , info )
360397 } )
361398
362- autoUpdater . on ( 'error' , ( error : Error ) => {
399+ updater . on ( 'error' , ( error : Error ) => {
363400 console . error ( 'Updater error:' , error )
364401 this . isDownloading = false
365402
@@ -380,11 +417,16 @@ export class UpdaterService {
380417 /**
381418 * Check for updates with retry logic
382419 */
383- private async checkWithRetry ( ) : Promise < UpdateInfo > {
420+ private async checkWithRetry ( ) : Promise < ElectronUpdateInfo > {
421+ const updater = getAutoUpdater ( )
422+ if ( ! updater ) {
423+ throw new Error ( 'electron-updater not available' )
424+ }
425+
384426 for ( let attempt = 0 ; attempt < MAX_RETRY_ATTEMPTS ; attempt ++ ) {
385427 try {
386428 this . retryCount = attempt
387- const result = await autoUpdater . checkForUpdates ( )
429+ const result = await updater . checkForUpdates ( )
388430
389431 if ( ! result ) {
390432 throw new Error ( 'No update information available' )
@@ -459,7 +501,7 @@ export class UpdaterService {
459501 /**
460502 * Check if version is compatible with current version
461503 */
462- private isVersionCompatible ( updateInfo : UpdateInfo ) : boolean {
504+ private isVersionCompatible ( updateInfo : ElectronUpdateInfo ) : boolean {
463505 // Basic compatibility check - can be enhanced
464506 // For now, just check if version is present
465507 return Boolean ( updateInfo . version )
0 commit comments