Extensible downloader system allowing custom download implementations for specialized requirements. The library provides a default got-based downloader but supports any custom implementation.
Generic interface that all downloader implementations must follow.
/**
* Generic interface for the artifact downloader library.
* The default implementation is GotDownloader,
* but any custom downloader can be passed to @electron/get via
* the ElectronDownloadRequestOptions.downloader option.
*/
interface Downloader<T> {
/**
* Download an artifact from an arbitrary URL to a file path on system
* @param url URL of the file to download
* @param targetFilePath Filesystem path to download the artifact to (including the file name)
* @param options Options to pass to the downloader
*/
download(url: string, targetFilePath: string, options: T): Promise<void>;
}Built-in downloader implementation using the got HTTP library.
/**
* Default Downloader implemented with got.
*/
class GotDownloader implements Downloader<GotDownloaderOptions> {
async download(
url: string,
targetFilePath: string,
options?: Partial<GotDownloaderOptions>
): Promise<void>;
}
/**
* Options for the default got Downloader implementation.
*/
type GotDownloaderOptions = GotOptions & { isStream?: true } & {
/** if defined, triggers every time got's downloadProgress event callback is triggered. */
getProgressCallback?: (progress: GotProgress) => Promise<void>;
/** if true, disables the console progress bar */
quiet?: boolean;
};Usage Examples:
import { download, GotDownloader } from "@electron/get";
// Use default downloader with custom options
await download('31.0.0', {
downloadOptions: {
timeout: { response: 60000 },
retry: { limit: 5 },
getProgressCallback: async (progress) => {
console.log(`Progress: ${Math.round(progress.percent * 100)}%`);
}
}
});
// Create custom GotDownloader instance
const customDownloader = new GotDownloader();
await download('31.0.0', {
downloader: customDownloader,
downloadOptions: {
headers: { 'Authorization': 'Bearer token123' }
}
});Create custom downloaders for specialized requirements.
type DownloadOptions = any; // Custom downloaders can implement any set of optionsCustom Downloader Example:
import { Downloader } from "@electron/get";
import fs from 'fs';
import https from 'https';
interface CustomDownloaderOptions {
timeout?: number;
retries?: number;
userAgent?: string;
}
class CustomDownloader implements Downloader<CustomDownloaderOptions> {
async download(
url: string,
targetFilePath: string,
options: CustomDownloaderOptions = {}
): Promise<void> {
const { timeout = 30000, retries = 3, userAgent = 'CustomDownloader/1.0' } = options;
for (let attempt = 0; attempt <= retries; attempt++) {
try {
await this.downloadWithTimeout(url, targetFilePath, timeout, userAgent);
return; // Success
} catch (error) {
if (attempt === retries) throw error;
await this.delay(1000 * Math.pow(2, attempt)); // Exponential backoff
}
}
}
private downloadWithTimeout(
url: string,
targetFilePath: string,
timeout: number,
userAgent: string
): Promise<void> {
return new Promise((resolve, reject) => {
const file = fs.createWriteStream(targetFilePath);
const request = https.get(url, {
headers: { 'User-Agent': userAgent },
timeout
}, response => {
if (response.statusCode !== 200) {
reject(new Error(`HTTP ${response.statusCode}`));
return;
}
response.pipe(file);
file.on('finish', () => {
file.close();
resolve();
});
});
request.on('error', reject);
request.on('timeout', () => {
request.destroy();
reject(new Error('Download timeout'));
});
});
}
private delay(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
// Use custom downloader
const customDownloader = new CustomDownloader();
await download('31.0.0', {
downloader: customDownloader,
downloadOptions: {
timeout: 60000,
retries: 5,
userAgent: 'MyApp/2.0'
}
});Progress information provided by the default downloader.
interface GotProgress {
/** Percentage of download completed (0-1) */
percent: number;
/** Bytes transferred so far */
transferred: number;
/** Total bytes to transfer */
total?: number;
}Progress Tracking Example:
import { download } from "@electron/get";
await download('31.0.0', {
downloadOptions: {
getProgressCallback: async (progress) => {
const percent = Math.round(progress.percent * 100);
const transferred = Math.round(progress.transferred / 1024 / 1024);
const total = progress.total ? Math.round(progress.total / 1024 / 1024) : '?';
console.log(`Download: ${percent}% (${transferred}MB / ${total}MB)`);
},
quiet: true // Disable built-in progress bar
}
});The built-in GotDownloader provides:
got library optionsinitializeProxy() is called