Electron Builder Runtime Utilities
builder-util-runtime is an internal utility package within the electron-builder ecosystem, providing core HTTP client functionalities, download progress tracking, and cancellation capabilities. It is primarily used by electron-builder and electron-updater for managing asset downloads, update checks, and publishing operations, rather than being directly consumed by end-user applications. The package ships with TypeScript type declarations, facilitating its use in TypeScript projects. It is part of the larger electron-builder monorepo, which typically follows an 8-week release cadence for major versions, aligning with Chromium's schedule, ensuring frequent updates and maintenance. The current stable version, as a dependency, is 9.6.0. Its main differentiators are its tight integration with the Electron build and update process and its focus on robust HTTP handling for Electron applications.
Common errors
-
TypeError: (0 , builder_util_runtime_1.createNetClient) is not a function
cause This typically occurs when attempting to use CommonJS `require()` syntax or incorrect destructuring to import an ESM named export, leading to the module object being imported but the function itself not being correctly resolved or called.fixEnsure you are using `import { createNetClient } from 'builder-util-runtime';` and that your project's TypeScript/Babel configuration correctly handles ESM output for Node.js. -
Error: UNABLE_TO_VERIFY_LEAF_SIGNATURE or ERR_SSL_CERT_HA_SS_IN_VALID
cause Network requests made by `builder-util-runtime` can fail due to SSL certificate issues, often caused by corporate proxies, firewalls, or misconfigured system root certificates, rather than a bug in the library itself.fixCheck your network environment for proxy settings. You might need to set `NODE_TLS_REJECT_UNAUTHORIZED='0'` (use with caution in production) or configure trusted certificates for Node.js, possibly by setting the `ELECTRON_GET_UNSAFE_HTTP` environment variable or providing custom `agent` options to the HTTP client if the API supports it. -
Error: Cannot find module 'builder-util-runtime'
cause The package is not installed as a direct dependency or a transitive dependency is missing or incorrectly resolved in your `node_modules`.fixRun `npm install builder-util-runtime` or `yarn add builder-util-runtime`. If it's a transitive dependency, try `npm install` or `yarn install` in your root project to ensure all dependencies are correctly hoisted and linked. Verify your `package.json` for proper declarations.
Warnings
- breaking As an internal utility within the electron-builder monorepo, builder-util-runtime's API is not guaranteed to be stable for direct consumption. Breaking changes may occur in patch or minor releases without explicit deprecation notices, as its primary consumers are electron-builder and electron-updater themselves. Direct usage should be approached with caution and thorough testing.
- gotcha The package leans towards an ESM-first architecture, shipping with `main` and `module` entries. While CJS `require()` might resolve, it can lead to unexpected `undefined` imports or module resolution issues, especially with named exports. Node.js >=12.0.0 is required, and modern Node.js environments favor ESM imports.
- deprecated Older versions of `builder-util-runtime` included support for Bintray, which was sunset. Any integrations relying on Bintray publishing options would have ceased to function.
Install
-
npm install builder-util-runtime -
yarn add builder-util-runtime -
pnpm add builder-util-runtime
Imports
- createNetClient
const { createNetClient } = require('builder-util-runtime')import { createNetClient } from 'builder-util-runtime' - ProgressCallbackTransform
import ProgressCallbackTransform from 'builder-util-runtime'
import { ProgressCallbackTransform } from 'builder-util-runtime' - HttpError
import { HttpError } from 'builder-util-runtime' - CancellationToken
import { CancellationToken } from 'builder-util-runtime'
Quickstart
import { createWriteStream } from 'fs';
import { createNetClient, ProgressCallbackTransform, HttpError, CancellationToken } from 'builder-util-runtime';
interface RequestOptions {
url: string;
headers?: Record<string, string>;
}
// A simplified representation of safeExecute, as the original might be internal or complex.
// This ensures the download operation is wrapped in a way that handles cancellation.
async function safeExecute<T>(task: () => Promise<T>, cancellationToken?: CancellationToken): Promise<T | undefined> {
if (cancellationToken?.isCancelled) {
console.log('Operation already cancelled.');
return undefined;
}
try {
return await task();
} catch (e) {
if (cancellationToken?.isCancelled) {
console.log('Operation cancelled during execution.');
return undefined;
}
throw e;
}
}
async function downloadFileWithProgress(url: string, outputPath: string) {
const client = createNetClient();
const cancellationToken = new CancellationToken();
const options: RequestOptions = {
url,
headers: {
'User-Agent': 'my-app-downloader/1.0.0',
'Accept': 'application/octet-stream'
},
};
const fileStream = createWriteStream(outputPath);
const progressStream = new ProgressCallbackTransform(0, (progress) => {
console.log(`Downloaded: ${progress.percent.toFixed(2)}% (${(progress.transferred / 1024 / 1024).toFixed(2)}MB / ${(progress.total / 1024 / 1024).toFixed(2)}MB)`);
});
try {
console.log(`Starting download from ${url} to ${outputPath}...`);
await safeExecute(() => client.download(options, fileStream, progressStream, cancellationToken), cancellationToken);
console.log(`Download complete: ${outputPath}`);
} catch (error) {
if (error instanceof HttpError) {
console.error(`HTTP Error ${error.statusCode}: ${error.message}`);
} else if (cancellationToken.isCancelled) {
console.log('Download operation was cancelled.');
} else {
console.error('An unexpected error occurred during download:', error);
}
} finally {
fileStream.close();
}
}
// Example usage: Download a small public file
// Replace with a valid URL to test, e.g., a small image or text file.
const dummyDownloadUrl = "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png";
const downloadPath = "./downloaded_google_logo.png";
downloadFileWithProgress(dummyDownloadUrl, downloadPath).catch(console.error);
// To demonstrate cancellation (uncomment to test):
// const cancelToken = new CancellationToken();
// downloadFileWithProgress(dummyDownloadUrl, "./cancel_test.png", cancelToken).catch(console.error);
// setTimeout(() => {
// console.log('Attempting to cancel download...');
// cancelToken.cancel();
// }, 500);