120 lines · 3.2 KB · TypeScript
RawDownload
/** * UpdaterService - Wraps electron-updater's autoUpdater for OTA updates. * * Forwards update lifecycle events to the renderer via IPC. * Auto-download is disabled so users must confirm before downloading. */ import { getErrorMessage } from '@shared/utils/errorHandling';import { createLogger } from '@shared/utils/logger';import electronUpdater from 'electron-updater'; const { autoUpdater } = electronUpdater; import type { UpdaterStatus } from '@shared/types';import type { BrowserWindow } from 'electron'; const logger = createLogger('UpdaterService'); export class UpdaterService {  private mainWindow: BrowserWindow | null = null;   constructor() {    autoUpdater.autoDownload = false;    autoUpdater.autoInstallOnAppQuit = true;     this.bindEvents();  }   /**   * Set the main window reference for sending status events.   */  setMainWindow(window: BrowserWindow | null): void {    this.mainWindow = window;  }   /**   * Check for available updates.   */  async checkForUpdates(): Promise<void> {    try {      await autoUpdater.checkForUpdates();    } catch (error) {      logger.error('Check for updates failed:', getErrorMessage(error));    }  }   /**   * Download the available update.   */  async downloadUpdate(): Promise<void> {    try {      await autoUpdater.downloadUpdate();    } catch (error) {      logger.error('Download update failed:', getErrorMessage(error));    }  }   /**   * Quit the app and install the downloaded update.   * On Windows (NSIS): isSilent=true runs the installer with /S (no wizard);   * isForceRunAfter=true launches the app after install. Other platforms ignore these.   */  quitAndInstall(): void {    autoUpdater.quitAndInstall(true, true);  }   private sendStatus(status: UpdaterStatus): void {    if (this.mainWindow && !this.mainWindow.isDestroyed()) {      this.mainWindow.webContents.send('updater:status', status);    }  }   private bindEvents(): void {    autoUpdater.on('checking-for-update', () => {      logger.info('Checking for update...');      this.sendStatus({ type: 'checking' });    });     autoUpdater.on('update-available', (info) => {      logger.info('Update available:', info.version);      this.sendStatus({        type: 'available',        version: info.version,        releaseNotes: typeof info.releaseNotes === 'string' ? info.releaseNotes : undefined,      });    });     autoUpdater.on('update-not-available', () => {      logger.info('No update available');      this.sendStatus({ type: 'not-available' });    });     autoUpdater.on('download-progress', (progress) => {      this.sendStatus({        type: 'downloading',        progress: {          percent: progress.percent,          transferred: progress.transferred,          total: progress.total,        },      });    });     autoUpdater.on('update-downloaded', (info) => {      logger.info('Update downloaded:', info.version);      this.sendStatus({        type: 'downloaded',        version: info.version,      });    });     autoUpdater.on('error', (error) => {      logger.error('Updater error:', getErrorMessage(error));      this.sendStatus({        type: 'error',        error: getErrorMessage(error),      });    });  }}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t