Comprehensive event system for monitoring the update lifecycle with both traditional EventEmitter events and type-safe signal handlers.
Type-safe event handler registration for updater events.
/**
* Type-safe event handler registration for updater events
* Provides an alternative to traditional EventEmitter.on() methods
*/
class UpdaterSignal {
constructor(emitter: EventEmitter);
/**
* Register handler for proxy authentication requests
* @param handler Function to handle authentication requests
*/
login(handler: LoginHandler): void;
/**
* Register handler for download progress updates
* @param handler Function to handle progress information
*/
progress(handler: (info: ProgressInfo) => void): void;
/**
* Register handler for successful update downloads
* @param handler Function to handle download completion
*/
updateDownloaded(handler: (info: UpdateDownloadedEvent) => void): void;
/**
* Register handler for cancelled updates
* @param handler Function to handle update cancellation
*/
updateCancelled(handler: (info: UpdateInfo) => void): void;
}
/**
* Login handler function type for proxy authentication
* @param authInfo Authentication information from Electron
* @param callback Callback function to provide credentials
*/
type LoginHandler = (authInfo: any, callback: LoginCallback) => void;
/**
* Login callback function for providing credentials
* @param username Optional username
* @param password Optional password
*/
type LoginCallback = (username?: string, password?: string) => void;Usage Examples:
import { autoUpdater } from "electron-updater";
// Type-safe signal handlers
autoUpdater.signals.progress((progressInfo) => {
console.log(`Download: ${progressInfo.percent}%`);
updateProgressBar(progressInfo.percent);
});
autoUpdater.signals.updateDownloaded((info) => {
console.log(`Update ${info.version} downloaded to: ${info.downloadedFile}`);
showRestartDialog();
});
autoUpdater.signals.updateCancelled((info) => {
console.log(`Update ${info.version} was cancelled`);
hideProgressIndicator();
});
autoUpdater.signals.login((authInfo, callback) => {
// Handle proxy authentication
showProxyLoginDialog((username, password) => {
callback(username, password);
});
});Standard EventEmitter events for the complete update lifecycle.
/**
* Complete typed event map for AppUpdater
*/
type AppUpdaterEvents = {
/**
* Emitted when an error occurs during any update operation
* @param error The error that occurred
* @param message Optional additional error message
*/
error: (error: Error, message?: string) => void;
/**
* Emitted when proxy authentication is required
* @param info Authentication information from Electron
* @param callback Callback to provide credentials
*/
login: (info: AuthInfo, callback: LoginCallback) => void;
/**
* Emitted when starting to check for updates
*/
"checking-for-update": () => void;
/**
* Emitted when no update is available
* @param info Information about the current version
*/
"update-not-available": (info: UpdateInfo) => void;
/**
* Emitted when an update is available for download
* @param info Information about the available update
*/
"update-available": (info: UpdateInfo) => void;
/**
* Emitted when an update has been successfully downloaded
* @param event Information about the downloaded update
*/
"update-downloaded": (event: UpdateDownloadedEvent) => void;
/**
* Emitted during download progress
* @param info Current download progress information
*/
"download-progress": (info: ProgressInfo) => void;
/**
* Emitted when an update operation is cancelled
* @param info Information about the cancelled update
*/
"update-cancelled": (info: UpdateInfo) => void;
/**
* Emitted when AppImage filename is updated (Linux only)
* @param path New path to the AppImage file
*/
"appimage-filename-updated": (path: string) => void;
}
/**
* Union type of all event names
*/
type UpdaterEvents = keyof AppUpdaterEvents;Usage Examples:
import { autoUpdater } from "electron-updater";
// Error handling
autoUpdater.on("error", (error, message) => {
console.error("Auto-updater error:", error);
if (message) {
console.error("Additional info:", message);
}
// Handle specific error types
if (error.message.includes("ENOTFOUND")) {
showOfflineMessage();
} else if (error.message.includes("ERR_UPDATER_INVALID_VERSION")) {
showInvalidVersionError();
}
});
// Update check lifecycle
autoUpdater.on("checking-for-update", () => {
console.log("Checking for updates...");
showCheckingIndicator();
});
autoUpdater.on("update-available", (info) => {
console.log("Update available:", info.version);
console.log("Release notes:", info.releaseNotes);
showUpdateAvailableDialog(info);
});
autoUpdater.on("update-not-available", (info) => {
console.log("App is up to date");
showUpToDateMessage();
});
// Download handling
autoUpdater.on("download-progress", (progressObj) => {
const percent = Math.round(progressObj.percent);
console.log(`Downloaded ${percent}% (${progressObj.transferred}/${progressObj.total})`);
console.log(`Speed: ${formatBytes(progressObj.bytesPerSecond)}/s`);
updateProgressBar(percent);
updateDownloadSpeed(progressObj.bytesPerSecond);
});
autoUpdater.on("update-downloaded", (info) => {
console.log("Update downloaded:", info.version);
console.log("Downloaded file:", info.downloadedFile);
showRestartPrompt(() => {
autoUpdater.quitAndInstall();
});
});
// Cancellation handling
autoUpdater.on("update-cancelled", (info) => {
console.log("Update cancelled:", info.version);
hideProgressBar();
showCancellationMessage();
});
// Platform-specific events
if (process.platform === "linux") {
autoUpdater.on("appimage-filename-updated", (path) => {
console.log("AppImage updated at:", path);
updateAppImagePath(path);
});
}
// Proxy authentication
autoUpdater.on("login", (authInfo, callback) => {
console.log("Proxy authentication required for:", authInfo.host);
// Show authentication dialog
showProxyDialog(authInfo, (credentials) => {
if (credentials) {
callback(credentials.username, credentials.password);
} else {
callback(); // Cancel authentication
}
});
});Utility functions for managing event handlers.
/**
* Add event handler with optional logging
* @param emitter EventEmitter instance
* @param event Event name
* @param handler Event handler function
*/
function addHandler(
emitter: EventEmitter,
event: UpdaterEvents,
handler: (...args: Array<any>) => void
): void;Usage Examples:
import { autoUpdater, addHandler } from "electron-updater";
// Add handler with automatic logging (if enabled)
addHandler(autoUpdater, "update-available", (info) => {
console.log("Update available:", info.version);
});
addHandler(autoUpdater, "download-progress", (progress) => {
updateUI(progress);
});A comprehensive example showing the complete event flow for an update cycle:
import { autoUpdater } from "electron-updater";
class UpdateManager {
private isUpdateAvailable = false;
private downloadInProgress = false;
constructor() {
this.setupEventHandlers();
}
private setupEventHandlers() {
// Start of update check
autoUpdater.on("checking-for-update", () => {
this.setStatus("Checking for updates...");
});
// Update check results
autoUpdater.on("update-available", (info) => {
this.isUpdateAvailable = true;
this.setStatus(`Update ${info.version} available`);
this.showUpdateDialog(info);
});
autoUpdater.on("update-not-available", () => {
this.setStatus("App is up to date");
});
// Download progress
autoUpdater.on("download-progress", (progress) => {
this.downloadInProgress = true;
this.updateProgressBar(progress.percent);
this.setStatus(`Downloading... ${Math.round(progress.percent)}%`);
});
// Download complete
autoUpdater.on("update-downloaded", (info) => {
this.downloadInProgress = false;
this.setStatus("Update ready for installation");
this.showInstallPrompt(info);
});
// Error handling
autoUpdater.on("error", (error, message) => {
this.downloadInProgress = false;
this.setStatus("Update failed");
this.showErrorDialog(error, message);
});
// Cancellation
autoUpdater.on("update-cancelled", (info) => {
this.downloadInProgress = false;
this.setStatus("Update cancelled");
this.hideProgressBar();
});
// Authentication
autoUpdater.on("login", (authInfo, callback) => {
this.handleProxyAuth(authInfo, callback);
});
}
private setStatus(message: string) {
console.log("Update status:", message);
// Update UI status
}
private updateProgressBar(percent: number) {
// Update progress bar UI
}
private showUpdateDialog(info: UpdateInfo) {
// Show dialog asking user if they want to download
const result = confirm(`Update ${info.version} is available. Download now?`);
if (result && autoUpdater.autoDownload === false) {
autoUpdater.downloadUpdate();
}
}
private showInstallPrompt(info: UpdateDownloadedEvent) {
// Show dialog asking user if they want to install now
const result = confirm("Update downloaded. Restart and install now?");
if (result) {
autoUpdater.quitAndInstall();
}
}
private showErrorDialog(error: Error, message?: string) {
console.error("Update error:", error);
// Show error dialog to user
}
private handleProxyAuth(authInfo: any, callback: LoginCallback) {
// Handle proxy authentication
const username = prompt("Proxy username:");
const password = prompt("Proxy password:");
callback(username, password);
}
// Public methods
public checkForUpdates() {
if (!this.downloadInProgress) {
autoUpdater.checkForUpdates();
}
}
public downloadUpdate() {
if (this.isUpdateAvailable && !this.downloadInProgress) {
autoUpdater.downloadUpdate();
}
}
public quitAndInstall() {
autoUpdater.quitAndInstall();
}
}
// Usage
const updateManager = new UpdateManager();
// Check for updates on app startup
app.whenReady().then(() => {
// Wait a few seconds after app startup
setTimeout(() => {
updateManager.checkForUpdates();
}, 3000);
});
// Check for updates periodically
setInterval(() => {
updateManager.checkForUpdates();
}, 10 * 60 * 1000); // Every 10 minutesConstants for event names to avoid typos and enable better IDE support.
/**
* Event name constants
*/
const DOWNLOAD_PROGRESS: "download-progress";
const UPDATE_DOWNLOADED: "update-downloaded";
/**
* All available event names
*/
const EVENT_NAMES = [
"checking-for-update",
"update-available",
"update-not-available",
"download-progress",
"update-downloaded",
"update-cancelled",
"error",
"login",
"appimage-filename-updated"
] as const;Usage Examples:
import { autoUpdater, DOWNLOAD_PROGRESS, UPDATE_DOWNLOADED } from "electron-updater";
// Use constants instead of string literals
autoUpdater.on(DOWNLOAD_PROGRESS, (info) => {
console.log(`Progress: ${info.percent}%`);
});
autoUpdater.on(UPDATE_DOWNLOADED, (info) => {
console.log("Update ready");
});
// Remove specific event listeners
const progressHandler = (info: ProgressInfo) => {
updateProgressIndicator(info.percent);
};
autoUpdater.on(DOWNLOAD_PROGRESS, progressHandler);
// Later, remove the specific handler
autoUpdater.removeListener(DOWNLOAD_PROGRESS, progressHandler);