📖 For tutorials, quick start, and conceptual guides, see README.md.
Import from electron-incremental-update:
import { createElectronApp, startupWithUpdater, autoUpdate } from 'electron-incremental-update'| Property | Type | Description |
|---|---|---|
mainPath? |
string |
Path to index file that make startupWithUpdater as default export Generate from plugin configuration by default |
updater? |
`(() => Promisable) | UpdaterOption` |
onInstall? |
OnInstallFunction |
Hooks on rename temp asar path to ${app.name}.asar |
beforeStart? |
(mainFilePath: string, logger?: Logger) => Promisable<void> |
Hooks before app startup @param mainFilePath main file path of ${app.name}.asar @param logger logger |
onStartError? |
(err: unknown, logger?: Logger) => void |
Hooks on app startup error @param err installing or startup error @param logger logger |
export interface AppOption {
/**
* Path to index file that make {@link startupWithUpdater} as default export
*
* Generate from plugin configuration by default
*/
mainPath?: string
/**
* Updater options
*/
updater?: (() => Promisable<Updater>) | UpdaterOption
/**
* Hooks on rename temp asar path to `${app.name}.asar`
*/
onInstall?: OnInstallFunction
/**
* Hooks before app startup
* @param mainFilePath main file path of `${app.name}.asar`
* @param logger logger
*/
beforeStart?: (mainFilePath: string, logger?: Logger) => Promisable<void>
/**
* Hooks on app startup error
* @param err installing or startup error
* @param logger logger
*/
onStartError?: (err: unknown, logger?: Logger) => void
}Utils to startup with updater
| Parameter | Type | Description |
|---|---|---|
fn |
(updater: Updater) => Promisable<void> |
startup function |
export function startupWithUpdater(
fn: (updater: Updater) => Promisable<void>,
): (updater: Updater) => Promisable<void> { /* ... */ }Example:
// in electron/main/index.ts
export default startupWithUpdater((updater) => {
updater.checkUpdate()
})Initialize Electron with updater
export async function createElectronApp(appOptions: AppOption = {}): Promise<void> { /* ... */ }Example:
createElectronApp({
updater: {
provider: new GitHubProvider({
username: 'yourname',
repo: 'electron',
}),
},
beforeStart(mainFilePath, logger) {
logger?.debug(mainFilePath)
},
})export type UpdaterErrorCode = 'ERR_DOWNLOAD' | 'ERR_VALIDATE' | 'ERR_PARAM' | 'ERR_NETWORK'export type UpdaterUnavailableCode = 'UNAVAILABLE_ERROR' | 'UNAVAILABLE_DEV' | 'UNAVAILABLE_VERSION'| Property | Type | Description |
|---|---|---|
provider? |
IProvider |
Update provider If you will not setup UpdateJSON or Buffer in params when checking update or download, this option is required |
SIGNATURE_CERT? |
string |
Certifaction key of signature, which will be auto generated by plugin, generate by selfsigned if not set |
receiveBeta? |
boolean |
Whether to receive beta update |
logger? |
Logger |
Updater logger |
getAppVersion? |
() => string |
Override current app version source. This is mainly used by dev tooling where the installed asar version differs from Electron's package version. |
export interface UpdaterOption {
/**
* Update provider
*
* If you will not setup `UpdateJSON` or `Buffer` in params when checking update or download, this option is **required**
*/
provider?: IProvider
/**
* Certifaction key of signature, which will be auto generated by plugin,
* generate by `selfsigned` if not set
*/
SIGNATURE_CERT?: string
/**
* Whether to receive beta update
*/
receiveBeta?: boolean
/**
* Updater logger
*/
logger?: Logger
/**
* Override current app version source.
*
* This is mainly used by dev tooling where the installed asar version differs
* from Electron's package version.
*/
getAppVersion?: () => string
}Update info with current app version and entry version
export type UpdateInfoWithExtraVersion = UpdateInfo & {
/**
* Current app version
*/
appVersion: string
/**
* Current entry version
*/
entryVersion: string
}Auto check update, download and install
export async function autoUpdate(updater: Updater): Promise<void> { /* ... */ }Bootstrap function that starts the Electron app, handles asar installation, loads the real main process, and initializes the updater.
function createElectronApp(appOptions?: AppOption): Promise<void>AppOption
| Property | Type | Description |
|---|---|---|
mainPath |
string |
Path to main file inside ${app.name}.asar. Defaults to __EIU_MAIN_FILE__. |
updater |
UpdaterOption | (() => Promisable<Updater>) |
Updater configuration or async factory. |
onInstall |
OnInstallFunction |
Hook before renaming temp asar. Default: install(); logger.info('update success!'). |
beforeStart |
(mainFilePath: string, logger?: Logger) => Promisable<void> |
Hook before loading the main module. |
onStartError |
(err: unknown, logger?: Logger) => void |
Hook called when main module fails to load. |
Wrapper for the main process default export. Provides the updater instance to the main function.
function startupWithUpdater(
fn: (updater: Updater) => Promisable<void>,
): (updater: Updater) => Promisable<void>Convenience helper for the full update flow: checks, downloads, and installs.
function autoUpdate(updater: Updater): Promise<void>EventEmitter-based class for the update lifecycle.
class Updater<T extends UpdateInfoWithExtraVersion = UpdateInfoWithExtraVersion> extends EventEmitterConstructor
new Updater(options?: UpdaterOption)Properties
| Property | Type | Description |
|---|---|---|
provider |
IProvider |
Update provider. |
receiveBeta |
boolean |
Whether to receive beta updates. |
logger |
Logger |
Logger instance. |
forceUpdate |
boolean |
Force update check (used in dev). |
Methods
| Method | Returns | Description |
|---|---|---|
checkForUpdates() |
Promise<boolean> |
Checks for available updates. Emits update-available or update-not-available. |
downloadUpdate() |
Promise<boolean> |
Downloads, decompresses, verifies, and writes the temp asar. Emits download-progress and update-downloaded. |
cancel() |
void |
Cancels an ongoing download. Emits update-cancelled. |
quitAndInstall() |
void |
Restarts the app to install the temp asar. |
Events
| Event | Payload | Description |
|---|---|---|
update-available |
T (extends UpdateInfoWithExtraVersion) |
A newer version is available. |
update-not-available |
code: UpdaterUnavailableCode, msg: string, info?: T |
No update is available. |
download-progress |
DownloadingInfo |
Download progress update. |
update-downloaded |
[] |
Update has been downloaded and verified. |
update-cancelled |
[] |
Download was cancelled. |
error |
UpdaterError |
An error occurred. |
Custom error with a machine-readable code.
class UpdaterError extends Error {
code: UpdaterErrorCode
constructor(code: UpdaterErrorCode, info: string)
}| Code | Description |
|---|---|
ERR_DOWNLOAD |
Download failed. |
ERR_VALIDATE |
Signature or integrity validation failed. |
ERR_PARAM |
Invalid parameters. |
ERR_NETWORK |
Network error. |
UpdaterOption
| Property | Type | Description |
|---|---|---|
provider |
IProvider |
Update provider. Required if not providing JSON/Buffer directly. |
SIGNATURE_CERT |
string |
Cert for signature verification. Auto-generated by plugin. |
receiveBeta |
boolean |
Whether to receive beta updates. |
logger |
Logger |
Logger instance. |
getAppVersion |
() => string |
Override current app version source. |
UpdaterErrorCode: 'ERR_DOWNLOAD' | 'ERR_VALIDATE' | 'ERR_PARAM' | 'ERR_NETWORK'
UpdaterUnavailableCode: 'UNAVAILABLE_ERROR' | 'UNAVAILABLE_DEV' | 'UNAVAILABLE_VERSION'
Logger
interface Logger {
info(msg: string): void
debug(msg: string): void
warn(msg: string): void
error(msg: string, e?: unknown): void
}UpdateInfoWithExtraVersion
type UpdateInfoWithExtraVersion = UpdateInfo & {
appVersion: string // current app version
entryVersion: string // current entry version
}Import from electron-incremental-update/provider:
import {
GitHubProvider,
GitHubAtomProvider,
GitHubApiProvider,
LocalDevProvider,
} from 'electron-incremental-update/provider'Safe get value from header
| Parameter | Type | Description |
|---|---|---|
headers |
Record<string, Arrayable<string>> |
response header |
key |
any |
target header key |
export function getHeader(headers: Record<string, Arrayable<string>>, key: any): any { /* ... */ }Default function to download json and parse to UpdateJson
| Parameter | Type | Description |
|---|---|---|
url |
string |
target url |
headers |
Record<string, any> |
extra headers |
signal |
AbortSignal |
abort signal |
resolveData |
ResolveDataFn |
on resolve |
export async function defaultDownloadText<T>(
url: string,
headers: Record<string, any>,
signal: AbortSignal,
resolveData: ResolveDataFn,
): Promise<T> { /* ... */ }Default function to download json and parse to UpdateJson
| Parameter | Type | Description |
|---|---|---|
url |
string |
target url |
headers |
Record<string, any> |
extra headers |
signal |
AbortSignal |
abort signal |
export async function defaultDownloadUpdateJSON(
url: string,
headers: Record<string, any>,
signal: AbortSignal,
): Promise<UpdateJSON> { /* ... */ }Default function to download asar buffer,
get total size from Content-Length header
| Parameter | Type | Description |
|---|---|---|
url |
string |
target url |
headers |
Record<string, any> |
extra headers |
signal |
AbortSignal |
abort signal |
onDownloading |
(progress: DownloadingInfo) => void |
on downloading callback |
export async function defaultDownloadAsar(
url: string,
headers: Record<string, any>,
signal: AbortSignal,
onDownloading?: (progress: DownloadingInfo) => void,
): Promise<Buffer> { /* ... */ }| Property | Type | Default | Description |
|---|---|---|---|
baseDir |
string |
— | Base directory for update files |
chunkSize? |
number |
64 * 1024 |
Local read chunk size for simulated download progress |
chunkDelay? |
number |
30 |
Delay between chunks in milliseconds |
export interface LocalDevProviderOptions {
/**
* Base directory for update files
*/
baseDir: string
/**
* Local read chunk size for simulated download progress
* @default 64 * 1024
*/
chunkSize?: number
/**
* Delay between chunks in milliseconds
* @default 30
*/
chunkDelay?: number
}Update Provider for local development
- download update json from
{baseDir}/{versionPath} - download update asar from
{baseDir}/{name}-{version}.asar.brThis provider is useful for testing updates during development without needing to deploy to a remote server.
| Parameter | Description |
|---|---|
options |
provider options |
export class LocalDevProvider extends BaseProvider { /* ... */ }export type UpdateInfoWithURL = UpdateInfo & { url: string }| Property | Type | Description |
|---|---|---|
delta |
number |
Download buffer delta |
percent |
number |
Downloaded percent, 0 ~ 100 If no Content-Length header, will be -1 |
total |
number |
Total size If not Content-Length header, will be -1 |
transferred |
number |
Downloaded size |
bps |
number |
Download speed, bytes per second |
export interface DownloadingInfo {
/**
* Download buffer delta
*/
delta: number
/**
* Downloaded percent, 0 ~ 100
*
* If no `Content-Length` header, will be -1
*/
percent: number
/**
* Total size
*
* If not `Content-Length` header, will be -1
*/
total: number
/**
* Downloaded size
*/
transferred: number
/**
* Download speed, bytes per second
*/
bps: number
}export type VersionJSON = UpdateInfoWithURL & { beta: UpdateInfoWithURL }| Property | Type | Description |
|---|---|---|
name |
string |
Provider name |
downloadJSON |
(name: string, versionPath: string, signal: AbortSignal) => Promise<VersionJSON> |
Download update json @param name app name @param versionPath normalized version path in project @param signal abort signal |
downloadAsar |
(updateInfo: UpdateInfoWithURL, signal: AbortSignal, onDownloading?: (info: DownloadingInfo) => void,) => Promise<Buffer> |
Download update asar buffer @param updateInfo existing update info @param signal abort signal @param onDownloading hook for on downloading |
isLowerVersion |
(oldVer: string, newVer: string) => boolean |
Check the old version is less than new version @param oldVer old version string @param newVer new version string |
decompressFile |
(buffer: Buffer) => Promise<Buffer> |
Function to decompress file using brotli @param buffer compressed file buffer |
verifySignature |
(buffer: Buffer, version: string, signature: string, cert: string,) => Promisable<boolean> |
Verify asar signature, if signature is valid, returns the version, otherwise returns undefined @param buffer file buffer @param version target version @param signature signature @param cert certificate |
export interface IProvider {
/**
* Provider name
*/
name: string
/**
* Download update json
* @param name app name
* @param versionPath normalized version path in project
* @param signal abort signal
*/
downloadJSON: (name: string, versionPath: string, signal: AbortSignal) => Promise<VersionJSON>
/**
* Download update asar buffer
* @param updateInfo existing update info
* @param signal abort signal
* @param onDownloading hook for on downloading
*/
downloadAsar: (
updateInfo: UpdateInfoWithURL,
signal: AbortSignal,
onDownloading?: (info: DownloadingInfo) => void,
) => Promise<Buffer>
/**
* Check the old version is less than new version
* @param oldVer old version string
* @param newVer new version string
*/
isLowerVersion: (oldVer: string, newVer: string) => boolean
/**
* Function to decompress file using brotli
* @param buffer compressed file buffer
*/
decompressFile: (buffer: Buffer) => Promise<Buffer>
/**
* Verify asar signature,
* if signature is valid, returns the version, otherwise returns `undefined`
* @param buffer file buffer
* @param version target version
* @param signature signature
* @param cert certificate
*/
verifySignature: (
buffer: Buffer,
version: string,
signature: string,
cert: string,
) => Promisable<boolean>
}Custom URL handler for GitHub provider, useful for mirrors and custom gateways
| Parameter | Description |
|---|---|
url |
original URL |
export type URLHandler = (url: URL) => Promisable<URL | string | undefined | null>Example:
(url) => {
url.hostname = 'mirror.ghproxy.com'
url.pathname = 'https://github.com' + url.pathname
return url
}Update Provider for Github API, you need to upload version.json to release as well
- check update from
https://api.github.com/repos/{user}/{repo}/releases?per_page=1 - download update json and get version and download url
- download update asar from update info
you can setup
urlHandlerin options to modify url before request
| Parameter | Description |
|---|---|
options |
provider options |
Extends: GitHubApiProviderOptions
export class GitHubApiProvider extends BaseGitHubProvider<GitHubApiProviderOptions> { /* ... */ }Update Provider for Github repo
- check update from
https://github.com/{user}/{repo}/releases.atom - download update json from
https://github.com/{user}/{repo}/releases/download/v{version}/{versionPath} - download update asar from
https://github.com/{user}/{repo}/releases/download/v{version}/{name}-{version}.asar.bryou can setupurlHandlerin options to modify url before request
| Parameter | Description |
|---|---|
options |
provider options |
export class GitHubAtomProvider extends BaseGitHubProvider { /* ... */ }| Property | Type | Description |
|---|---|---|
user |
string |
Github user name |
repo |
string |
Github repo name |
extraHeaders? |
Record<string, string> |
Extra headers |
urlHandler? |
URLHandler |
Custom url handler (some public CDN links). See URLHandler for details. |
export interface BaseGitHubProviderOptions {
/**
* Github user name
*/
user: string
/**
* Github repo name
*/
repo: string
/**
* Extra headers
*/
extraHeaders?: Record<string, string>
/**
* Custom url handler ([some public CDN links](https://github.com/XIU2/UserScript/blob/master/GithubEnhanced-High-Speed-Download.user.js#L40)). See {@link URLHandler} for details.
*/
urlHandler?: URLHandler
}Extends: BaseGitHubProviderOptions
| Property | Type | Default | Description |
|---|---|---|---|
branch? |
string |
'HEAD' |
Github branch name that fetch version |
export interface GitHubProviderOptions extends BaseGitHubProviderOptions {
/**
* Github branch name that fetch version
* @default 'HEAD'
*/
branch?: string
}Update Provider for Github repo
- download update json from
https://github.com/{user}/{repo}/raw/HEAD/{versionPath} - download update asar from
https://github.com/{user}/{repo}/releases/download/v{version}/{name}-{version}.asar.bryou can setupurlHandlerin options to modify url before request
| Parameter | Description |
|---|---|
options |
provider options |
Extends: GitHubProviderOptions
export class GitHubProvider extends BaseGitHubProvider<GitHubProviderOptions> { /* ... */ }The contract all providers must implement.
interface IProvider {
name: string
downloadJSON(name: string, versionPath: string, signal: AbortSignal): Promise<VersionJSON>
downloadAsar(
updateInfo: UpdateInfoWithURL,
signal: AbortSignal,
onDownloading?: (info: DownloadingInfo) => void,
): Promise<Buffer>
isLowerVersion(oldVer: string, newVer: string): boolean
decompressFile(buffer: Buffer): Promise<Buffer>
verifySignature(
buffer: Buffer,
version: string,
signature: string,
cert: string,
): Promisable<boolean>
}| Method | Description |
|---|---|
downloadJSON |
Downloads and parses version.json. |
downloadAsar |
Downloads the compressed asar file. |
isLowerVersion |
Compares two version strings. Returns true if oldVer < newVer. |
decompressFile |
Decompresses the asar buffer. |
verifySignature |
Verifies the asar signature against the cert. |
Reads version.json from a GitHub repository branch and downloads the asar from GitHub Releases.
import { GitHubProvider } from 'electron-incremental-update/provider'
const provider = new GitHubProvider({
user: 'your-github-user',
repo: 'your-repo',
branch: 'HEAD',
})Constructor options
| Option | Type | Default | Description |
|---|---|---|---|
user |
string |
required | GitHub user or organization. |
repo |
string |
required | GitHub repository name. |
branch |
string |
'HEAD' |
Branch to read version.json from. |
extraHeaders |
Record<string, string> |
— | Extra HTTP headers for requests. |
urlHandler |
URLHandler |
— | Transform URLs before requests (mirrors, gateways). |
Default URLs:
- update JSON:
https://github.com/{user}/{repo}/raw/{branch}/{versionPath} - asar:
https://github.com/{user}/{repo}/releases/download/v{version}/{name}-{version}.asar.br
Reads the latest release tag from releases.atom, then fetches update JSON and asar from that release.
import { GitHubAtomProvider } from 'electron-incremental-update/provider'
const provider = new GitHubAtomProvider({
user: 'your-github-user',
repo: 'your-repo',
})Constructor options: Same as GitHubProvider minus branch.
Uses the GitHub Releases API. Supports a token for private repos or higher rate limits.
import { GitHubApiProvider } from 'electron-incremental-update/provider'
const provider = new GitHubApiProvider({
user: 'your-github-user',
repo: 'your-repo',
token: process.env.GITHUB_TOKEN,
})Constructor options: Same as GitHubProvider minus branch, plus:
| Option | Type | Description |
|---|---|---|
token |
string |
GitHub personal access token. |
All GitHub providers support urlHandler for mirrors, custom gateways, or request rewriting.
const provider = new GitHubProvider({
user: 'your-github-user',
repo: 'your-repo',
urlHandler(url) {
url.hostname = 'mirror.example.com'
url.pathname = `https://github.com${url.pathname}`
return url
},
})Reads update metadata and compressed asar from the local filesystem. Used for development testing.
import { LocalDevProvider } from 'electron-incremental-update/provider'
const provider = new LocalDevProvider({
baseDir: 'release/local-update',
chunkSize: 32 * 1024,
chunkDelay: 50,
})Constructor options
| Option | Type | Default | Description |
|---|---|---|---|
baseDir |
string |
required | Directory containing version.json and asar. |
chunkSize |
number |
64 * 1024 |
Simulated download chunk size in bytes. |
chunkDelay |
number |
30 |
Delay between chunks in milliseconds. |
It reads from:
{baseDir}/{versionPath}{baseDir}/{name}-{version}.asar.br
Prefer
localDevUpdate: truein the Vite plugin over constructingLocalDevProvidermanually. See Plugin Options.
UpdateInfo
interface UpdateInfo {
signature: string
minimumVersion: string
version: string
}UpdateInfoWithURL: UpdateInfo & { url: string }
VersionJSON: UpdateInfoWithURL & { beta: UpdateInfoWithURL }
DownloadingInfo
interface DownloadingInfo {
delta: number // download buffer delta
percent: number // 0-100, or -1 if Content-Length unknown
total: number // total bytes, or -1 if unknown
transferred: number // downloaded bytes
bps: number // bytes per second
}URLHandler: (url: URL) => Promisable<URL | string | undefined | null>
Import from electron-incremental-update/vite:
import { electronWithUpdater, defineElectronConfig } from 'electron-incremental-update/vite'Filter error messages from stdout/stderr during startup
| Parameter | Type | Description |
|---|---|---|
args |
`` | Startup arguments |
filter |
(msg: string) => boolean |
Filter function to determine which messages to show |
export async function filterErrorMessageStartup(filter: (msg: string) => boolean): Promise<void> { /* ... */ }Fix Windows character encoding by setting code page to UTF-8
- @returns Wrapped function with Windows encoding fix
| Parameter | Type | Description |
|---|---|---|
fn |
T |
Function to wrap with encoding fix |
export function fixWinCharEncoding<T extends AnyFunction>(fn: T): T { /* ... */ }Base on vite-plugin-electron/multi-env
- integrate with updater
- no
rendererconfig - remove old output file
- externalize dependencies
- auto restart when entry file changes
You can override all the environment configs, except output directories (use
options.updater.paths.electronDistPathinstead)
export async function electronWithUpdater(
options: ElectronWithUpdaterOptions,
): Promise<Plugin[] | undefined> { /* ... */ }Example:
import { defineConfig } from 'vite'
import { electronWithUpdater } from 'electron-incremental-update/vite'
export default defineConfig(async ({ command }) => {
const isBuild = command === 'build'
return {
plugins: [
electronWithUpdater({
isBuild,
main: {
files: ['./electron/main/index.ts', './electron/main/worker.ts'],
},
preload: {
files: './electron/preload/index.ts',
},
updater: {
// options
}
}),
],
}
})Extends: ElectronWithUpdaterOptions
| Property | Type | Default | Description |
|---|---|---|---|
root? |
string |
process.cwd() |
Root dir of project |
renderer? |
Omit<UserConfig, 'root'> |
— | Config for renderer process |
export interface ElectronViteHelperOptions extends ElectronWithUpdaterOptions {
/**
* Root dir of project
* @default process.cwd()
*/
root?: string
/**
* Config for renderer process
*/
renderer?: Omit<UserConfig, 'root'>
}Vite config helper
See also: electronWithUpdater
export function defineElectronConfig(options: ElectronViteHelperOptions): UserConfig { /* ... */ }Example:
import { defineElectronConfig } from 'electron-incremental-update/vite'
export default defineElectronConfig({
// root: './apps'
main: {
files: ['./electron/main/index.ts', './electron/main/worker.ts'],
},
preload: {
files: './electron/preload/index.ts',
},
updater: {
// options
},
renderer: {
// plugins: []
}
})| Property | Type | Description |
|---|---|---|
files |
NonNullable<MultiEnvElectronOptions['input']> |
Shortcut of build.rolldownOptions.input |
options? |
MultiEnvElectronOptions['options'] & { build?: { outDir: never sourcemap: never minify: never rolldownOptions?: { output?: { dir: never } } } } |
Override vite options |
export interface CommonBuildOption {
/**
* Shortcut of `build.rolldownOptions.input`
*/
files: NonNullable<MultiEnvElectronOptions['input']>
/**
* Override vite options
*/
options?: MultiEnvElectronOptions['options'] & {
build?: {
outDir: never
sourcemap: never
minify: never
rolldownOptions?: {
output?: {
dir: never
}
}
}
}
}Extends: Pick
| Property | Type | Default | Description |
|---|---|---|---|
bundleDeps? |
MultiEnvElectronOptions['bundleDeps'] |
— | electron-incremental-update and its subpath imports are always bundled, regardless of this dependency policy. |
sourcemap? |
boolean |
`!isBuild | |
minify? |
boolean |
isBuild |
Whether to minify the code |
bytecode? |
`boolean | BytecodeOptions` | — |
buildVersionJson? |
boolean |
isCI |
Whether to generate version json |
localDevUpdate? |
`boolean | LocalDevUpdateOptions` | false |
external? |
`(string | RegExp)[] | boolean` |
entry |
{ /** * By default, all the unbundled modules will be packaged by packager like electron-builder. * If setup, all the dependenciesinpackage.jsonwill be bundled by default, and you need * to manually handle the native module files. * * If you are usingelectron-buidler, don't forget to append '!node_modules/**'in * electron-build config'sfilesarray */ postBuild?: (args: { /** * Whether is in build mode */ isBuild: boolean /** * Get path fromentryOutputDirPath*/ getPathFromEntryOutputDir: (...paths: string[]) => string /** * Check exist and copy file toentryOutputDirPath* * Iftoabsent, set tobasename(from)* * IfskipIfExistabsent, skip copy iftoexist */ copyToEntryOutputDir: (options: { from: string to?: string /** * Skip copy iftoexist * @default true */ skipIfExist?: boolean }) => void /** * Copy specified modules to entry output dir, just likeexternaloption in rolldown */ copyModules: (options: { /** * External Modules */ modules: string[] /** * Skip copy ifto exist * @default true */ skipIfExist?: boolean }) => void }) => Promisable<void> } & CommonBuildOption |
— | Options for entry (app.asar) To change output directories, use options.updater.paths.electronDistPath instead |
main |
{ /** * Electron App startup function. * * It will mount the Electron App child-process to process.electronApp. * @param argv default value ['.', '--no-sandbox']* @param options options forchild_process.spawn * @param customElectronPkg custom electron package name (default: 'electron') */ onstart?: MultiEnvElectronOptions['onstart'] } & CommonBuildOption |
— | Main process options To change output directories, use options.updater.paths.electronDistPath instead |
preload? |
CommonBuildOption |
— | Preload process options To change output directories, use options.updater.paths.electronDistPath instead |
updater? |
UpdaterOptions |
— | Updater options |
export interface ElectronWithUpdaterOptions extends Pick<MultiEnvElectronOptions, 'bundleDeps'> {
/**
* `electron-incremental-update` and its subpath imports are always bundled,
* regardless of this dependency policy.
*/
bundleDeps?: MultiEnvElectronOptions['bundleDeps']
/**
* Whether to generate sourcemap
* @default !isBuild || !!process.env.VSCODE_DEBUG
*/
sourcemap?: boolean
/**
* Whether to minify the code
* @default isBuild
*/
minify?: boolean
/**
* Whether to generate bytecode
*
* **Only support CommonJS**
*
* Only main process by default, if you want to use in preload script, please use `electronWithUpdater({ bytecode: { enablePreload: true } })` and set `sandbox: false` when creating window
*/
bytecode?: boolean | BytecodeOptions
/**
* Whether to generate version json
* @default isCI
*/
buildVersionJson?: boolean
/**
* Generate and serve a local update package during dev startup.
*
* This is useful for testing update checks, simulated download progress,
* and restart/install behavior without publishing a remote release.
*
* @default false
*/
localDevUpdate?: boolean | LocalDevUpdateOptions
/**
* Addtional `external` option in `build.rolldownOptions`,
*
* If equals `true`,
* external `dependencies` in `package.json` by default
*/
external?: (string | RegExp)[] | boolean
/**
* Options for entry (app.asar)
*
* To change output directories, use `options.updater.paths.electronDistPath` instead
*/
entry: {
/**
* By default, all the unbundled modules will be packaged by packager like `electron-builder`.
* If setup, all the `dependencies` in `package.json` will be bundled by default, and you need
* to manually handle the native module files.
*
* If you are using `electron-buidler`, don't forget to append `'!node_modules/**'` in
* electron-build config's `files` array
*/
postBuild?: (args: {
/**
* Whether is in build mode
*/
isBuild: boolean
/**
* Get path from `entryOutputDirPath`
*/
getPathFromEntryOutputDir: (...paths: string[]) => string
/**
* Check exist and copy file to `entryOutputDirPath`
*
* If `to` absent, set to `basename(from)`
*
* If `skipIfExist` absent, skip copy if `to` exist
*/
copyToEntryOutputDir: (options: {
from: string
to?: string
/**
* Skip copy if `to` exist
* @default true
*/
skipIfExist?: boolean
}) => void
/**
* Copy specified modules to entry output dir, just like `external` option in rolldown
*/
copyModules: (options: {
/**
* External Modules
*/
modules: string[]
/**
* Skip copy if `to` exist
* @default true
*/
skipIfExist?: boolean
}) => void
}) => Promisable<void>
} & CommonBuildOption
/**
* Main process options
*
* To change output directories, use `options.updater.paths.electronDistPath` instead
*/
main: {
/**
* Electron App startup function.
*
* It will mount the Electron App child-process to `process.electronApp`.
* @param argv default value `['.', '--no-sandbox']`
* @param options options for `child_process.spawn`
* @param customElectronPkg custom electron package name (default: 'electron')
*/
onstart?: MultiEnvElectronOptions['onstart']
} & CommonBuildOption
/**
* Preload process options
*
* To change output directories, use `options.updater.paths.electronDistPath` instead
*/
preload?: CommonBuildOption
/**
* Updater options
*/
updater?: UpdaterOptions
}| Property | Type | Default | Description |
|---|---|---|---|
packageJsonPath? |
string |
project package.json |
Package file used for local dev update name/version. This is useful when the Electron app package is not the project root package, such as a playground or example app. |
baseDir? |
string |
'release/local-update' |
Directory that contains local update resources. The generated version file is written under {baseDir}/{versionPath} and update archives are written as {baseDir}/{name}-{version}.asar.br. |
chunkSize? |
number |
LocalDevProvider default |
Local read chunk size for simulated download progress. |
chunkDelay? |
number |
LocalDevProvider default |
Delay between simulated progress chunks in milliseconds. |
export interface LocalDevUpdateOptions {
/**
* Package file used for local dev update name/version.
*
* This is useful when the Electron app package is not the project root
* package, such as a playground or example app.
*
* @default project package.json
*/
packageJsonPath?: string
/**
* Directory that contains local update resources.
*
* The generated version file is written under `{baseDir}/{versionPath}` and
* update archives are written as `{baseDir}/{name}-{version}.asar.br`.
*
* @default 'release/local-update'
*/
baseDir?: string
/**
* Local read chunk size for simulated download progress.
*
* @default LocalDevProvider default
*/
chunkSize?: number
/**
* Delay between simulated progress chunks in milliseconds.
*
* @default LocalDevProvider default
*/
chunkDelay?: number
}| Property | Type | Default | Description |
|---|---|---|---|
minimumVersion? |
string |
'0.0.0' |
Minimum version of entry |
paths? |
{ /** * Path to asar file * @default release/${app.name}.asar*/ asarOutputPath?: string /** * Path to app entry output file * @default 'dist-entry' */ entryOutDir?: string /** * Path to version info output, content is {@link UpdateJSON} * @defaultrelease/version.json*/ versionPath?: string /** * Path to compressed asar file * @defaultrelease/${app.name}-${version}.asar.br*/ compressedPath?: string /** * Path to electron build output * @defaultdist-electron*/ electronDistPath?: string /** * Path to renderer build output * @defaultdist */ rendererDistPath?: string } |
— | Options for paths |
keys? |
{ /** * Path to the pem file that contains private key * If not ended with .pem, it will be appended * * **If UPDATER_PKis set, will read it instead of read fromprivateKeyPath** * @default 'keys/private.pem' */ privateKeyPath?: string /** * Path to the pem file that contains public key * If not ended with .pem, it will be appended * * **If UPDATER_CERTis set, will read it instead of read fromcertPath** * @default 'keys/cert.pem' */ certPath?: string /** * Length of the key * @default 2048 */ keyLength?: number /** * X509 certificate info * * Only generate simple **self-signed** certificate **without extensions** */ certInfo?: { /** * The subject of the certificate * * @default { commonName: ${app.name}, organizationName: org.${app.name} } */ subject?: DistinguishedName /** * Expire days of the certificate * * @default 3650 */ days?: number } } |
— | signature config |
export interface UpdaterOptions {
/**
* Minimum version of entry
* @default '0.0.0'
*/
minimumVersion?: string
/**
* Options for paths
*/
paths?: {
/**
* Path to asar file
* @default `release/${app.name}.asar`
*/
asarOutputPath?: string
/**
* Path to app entry output file
* @default 'dist-entry'
*/
entryOutDir?: string
/**
* Path to version info output, content is {@link UpdateJSON}
* @default `release/version.json`
*/
versionPath?: string
/**
* Path to compressed asar file
* @default `release/${app.name}-${version}.asar.br`
*/
compressedPath?: string
/**
* Path to electron build output
* @default `dist-electron`
*/
electronDistPath?: string
/**
* Path to renderer build output
* @default `dist`
*/
rendererDistPath?: string
}
/**
* signature config
*/
keys?: {
/**
* Path to the pem file that contains private key
* If not ended with .pem, it will be appended
*
* **If `UPDATER_PK` is set, will read it instead of read from `privateKeyPath`**
* @default 'keys/private.pem'
*/
privateKeyPath?: string
/**
* Path to the pem file that contains public key
* If not ended with .pem, it will be appended
*
* **If `UPDATER_CERT` is set, will read it instead of read from `certPath`**
* @default 'keys/cert.pem'
*/
certPath?: string
/**
* Length of the key
* @default 2048
*/
keyLength?: number
/**
* X509 certificate info
*
* Only generate simple **self-signed** certificate **without extensions**
*/
certInfo?: {
/**
* The subject of the certificate
*
* @default { commonName: `${app.name}`, organizationName: `org.${app.name}` }
*/
subject?: DistinguishedName
/**
* Expire days of the certificate
*
* @default 3650
*/
days?: number
}
}
overrideGenerator?: GeneratorOverrideFunctions
}| Property | Type | Description |
|---|---|---|
generateSignature? |
(buffer: Buffer, privateKey: string, cert: string, version: string,) => Promisable<string> |
Custom signature generate function @param buffer file buffer @param privateKey private key @param cert certificate string, EOL must be \n @param version current version |
generateUpdateJson? |
(existingJson: UpdateJSON, signature: string, version: string, minVersion: string,) => Promisable<UpdateJSON> |
Custom generate update json function @param existingJson The existing JSON object. @param signature generated signature @param version current version @param minVersion The minimum version |
generateCompressedFile? |
(buffer: Buffer) => Promisable<Buffer> |
Custom generate compressed file buffer @param buffer source buffer |
export interface GeneratorOverrideFunctions {
/**
* Custom signature generate function
* @param buffer file buffer
* @param privateKey private key
* @param cert certificate string, **EOL must be `\n`**
* @param version current version
*/
generateSignature?: (
buffer: Buffer,
privateKey: string,
cert: string,
version: string,
) => Promisable<string>
/**
* Custom generate update json function
* @param existingJson The existing JSON object.
* @param signature generated signature
* @param version current version
* @param minVersion The minimum version
*/
generateUpdateJson?: (
existingJson: UpdateJSON,
signature: string,
version: string,
minVersion: string,
) => Promisable<UpdateJSON>
/**
* Custom generate compressed file buffer
* @param buffer source buffer
*/
generateCompressedFile?: (buffer: Buffer) => Promisable<Buffer>
}All option types are auto-generated from JSDoc in the source code. See the sections above for
ElectronWithUpdaterOptions,CommonBuildOption,UpdaterOptions,LocalDevUpdateOptions,BytecodeOptions,ElectronViteHelperOptions, etc.
Import from electron-incremental-update/utils:
import {
aesDecrypt,
aesEncrypt,
beautifyDevTools,
defaultIsLowerVersion,
defaultSignature,
defaultDecompressFile,
defaultVerifySignature,
defaultCompressFile,
getAppVersion,
getEntryVersion,
getPathFromAppNameAsar,
getPathFromEntryAsar,
getPathFromMain,
getPathFromPreload,
getPathFromPublic,
handleUnexpectedErrors,
hashBuffer,
importNative,
isDev,
isLinux,
isMac,
isWin,
loadPage,
parseVersion,
requireNative,
restartApp,
setAppUserModelId,
setPortableDataPath,
singleInstance,
} from 'electron-incremental-update/utils'Default function to generate asar signature, returns generated signature
| Parameter | Type | Description |
|---|---|---|
buffer |
Buffer |
file buffer |
privateKey |
string |
primary key |
cert |
string |
certificate |
version |
string |
target version |
export function defaultSignature(
buffer: Buffer,
privateKey: string,
cert: string,
version: string,
): string { /* ... */ }Default function to verify asar signature,
if signature is valid, returns the version, otherwise returns undefined
| Parameter | Type | Description |
|---|---|---|
buffer |
Buffer |
file buffer |
version |
string |
target version |
signature |
string |
signature |
cert |
string |
certificate |
export function defaultVerifySignature(
buffer: Buffer,
version: string,
signature: string,
cert: string,
): boolean { /* ... */ }Safe get value from header
| Parameter | Type | Description |
|---|---|---|
headers |
Record<string, Arrayable<string>> |
response header |
key |
any |
target header key |
export function getHeader(headers: Record<string, Arrayable<string>>, key: any): any { /* ... */ }Default function to download json and parse to UpdateJson
| Parameter | Type | Description |
|---|---|---|
url |
string |
target url |
headers |
Record<string, any> |
extra headers |
signal |
AbortSignal |
abort signal |
resolveData |
ResolveDataFn |
on resolve |
export async function defaultDownloadText<T>(
url: string,
headers: Record<string, any>,
signal: AbortSignal,
resolveData: ResolveDataFn,
): Promise<T> { /* ... */ }Default function to download json and parse to UpdateJson
| Parameter | Type | Description |
|---|---|---|
url |
string |
target url |
headers |
Record<string, any> |
extra headers |
signal |
AbortSignal |
abort signal |
export async function defaultDownloadUpdateJSON(
url: string,
headers: Record<string, any>,
signal: AbortSignal,
): Promise<UpdateJSON> { /* ... */ }Default function to download asar buffer,
get total size from Content-Length header
| Parameter | Type | Description |
|---|---|---|
url |
string |
target url |
headers |
Record<string, any> |
extra headers |
signal |
AbortSignal |
abort signal |
onDownloading |
(progress: DownloadingInfo) => void |
on downloading callback |
export async function defaultDownloadAsar(
url: string,
headers: Record<string, any>,
signal: AbortSignal,
onDownloading?: (progress: DownloadingInfo) => void,
): Promise<Buffer> { /* ... */ }Compile time dev check
export const isDev = __EIU_IS_DEV__Get joined path of ${electron.app.name}.asar (not app.asar)
If is in dev, always return 'DEV.asar'
export function getPathFromAppNameAsar(...paths: string[]): string { /* ... */ }Get app version, if is in dev, return getEntryVersion()
export function getAppVersion(): string { /* ... */ }Get entry version
export function getEntryVersion(): string { /* ... */ }Use require to load native module from entry asar
| Parameter | Type | Description |
|---|---|---|
moduleName |
string |
file name in entry |
export function requireNative<T = any>(moduleName: string): T { /* ... */ }Example:
requireNative<typeof import('../native/db')>('db')Use import to load native module from entry asar
| Parameter | Type | Description |
|---|---|---|
moduleName |
string |
file name in entry |
export async function importNative<T = any>(moduleName: string): Promise<T> { /* ... */ }Example:
await importNative<typeof import('../native/db')>('db')Restarts the Electron app.
export function restartApp(): void { /* ... */ }Fix app use model id, only for Windows
| Parameter | Type | Description |
|---|---|---|
id |
string |
app id, default is org.${electron.app.name} |
export function setAppUserModelId(id?: string): void { /* ... */ }Disable hardware acceleration for Windows 7 Only support CommonJS
export function disableHWAccForWin7(): void { /* ... */ }Keep single electron instance and auto restore window on second-instance event
| Parameter | Type | Description |
|---|---|---|
window |
BrowserWindow |
brwoser window to show |
export function singleInstance(window?: BrowserWindow): void { /* ... */ }Set userData dir to the dir of .exe file
Useful for portable Windows app
| Parameter | Type | Description |
|---|---|---|
dirName |
string |
dir name, default to data |
create |
boolean |
whether to create dir, default to true |
export function setPortableDataPath(dirName: string = 'data', create: boolean = true): void { /* ... */ }Load process.env.VITE_DEV_SERVER_URL when dev, else load html file
| Parameter | Type | Description |
|---|---|---|
win |
BrowserWindow |
window |
htmlFilePath |
`` | html file path, default is index.html |
export function loadPage(win: BrowserWindow, htmlFilePath = 'index.html'): void { /* ... */ }Beautify devtools' font and scrollbar See also: electron/electron#42055
| Parameter | Type | Description |
|---|---|---|
win |
BrowserWindow |
target window |
options |
BeautifyDevToolsOptions |
sans font family, mono font family and scrollbar |
export function beautifyDevTools(win: BrowserWindow, options: BeautifyDevToolsOptions): void { /* ... */ }Get joined path from main dir
| Parameter | Description |
|---|---|
paths |
rest paths |
export function getPathFromMain(...paths: string[]): string { /* ... */ }Get joined path from preload dir
| Parameter | Description |
|---|---|
paths |
rest paths |
export function getPathFromPreload(...paths: string[]): string { /* ... */ }Get joined path from publich dir
| Parameter | Description |
|---|---|
paths |
rest paths |
export function getPathFromPublic(...paths: string[]): string { /* ... */ }Get joined path from entry asar
| Parameter | Description |
|---|---|
paths |
rest paths |
export function getPathFromEntryAsar(...paths: string[]): string { /* ... */ }Handle all unhandled error
| Parameter | Type | Description |
|---|---|---|
callback |
(err: unknown) => void |
callback function |
export function handleUnexpectedErrors(callback: (err: unknown) => void): void { /* ... */ }| Property | Type | Description |
|---|---|---|
major |
number |
4 of 4.3.2-beta.1 |
minor |
number |
3 of 4.3.2-beta.1 |
patch |
number |
2 of 4.3.2-beta.1 |
stage |
string |
beta of 4.3.2-beta.1 |
stageVersion |
number |
1 of 4.3.2-beta.1 |
export interface Version {
/**
* `4` of `4.3.2-beta.1`
*/
major: number
/**
* `3` of `4.3.2-beta.1`
*/
minor: number
/**
* `2` of `4.3.2-beta.1`
*/
patch: number
/**
* `beta` of `4.3.2-beta.1`
*/
stage: string
/**
* `1` of `4.3.2-beta.1`
*/
stageVersion: number
}Parse version string to {
Version}, like 0.2.0-beta.1
Supported format: major.minor.patch[-stage[.stageVersion]]
Build metadata (+build) and complex semver prerelease identifiers
(e.g. 1.0.0-beta.1.2) are not supported yet.
| Parameter | Type | Description |
|---|---|---|
version |
string |
version string |
export function parseVersion(version: string): Version { /* ... */ }Default function to check the old version is less than new version
| Parameter | Type | Description |
|---|---|---|
oldVer |
string |
old version string |
newVer |
string |
new version string |
export function defaultIsLowerVersion(oldVer: string, newVer: string): boolean { /* ... */ }Update info json
export interface UpdateInfo {
/**
* Update Asar signature
*/
signature: string
/**
* Minimum version
*/
minimumVersion: string
/**
* Target version
*/
version: string
}{ UpdateInfo} with beta
export type UpdateJSON = UpdateInfo & {
/**
* Beta update info
*/
beta: UpdateInfo
}Check is UpdateJSON
| Parameter | Type | Description |
|---|---|---|
json |
object |
any variable |
export function isUpdateJSON(json: object): json is UpdateJSON { /* ... */ }Default function to generate UpdateJSON
| Parameter | Type | Description |
|---|---|---|
existingJson |
UpdateJSON |
exising update json |
signature |
string |
sigature |
version |
string |
target version |
minimumVersion |
string |
minimum version |
export function defaultVersionJsonGenerator(
existingJson: UpdateJSON,
signature: string,
version: string,
minimumVersion: string,
): UpdateJSON { /* ... */ }Default function to compress file using brotli
| Parameter | Type | Description |
|---|---|---|
buffer |
Buffer |
uncompressed file buffer |
export async function defaultCompressFile(buffer: Buffer): Promise<Buffer> { /* ... */ }Default function to decompress file using brotli
| Parameter | Type | Description |
|---|---|---|
buffer |
Buffer |
compressed file buffer |
export async function defaultDecompressFile(buffer: Buffer): Promise<Buffer> { /* ... */ }| Function | Description |
|---|---|
getPathFromAppNameAsar(...paths) |
Path inside ${app.name}.asar. In dev, returns DEV.asar. |
getPathFromEntryAsar(...paths) |
Path inside app.asar. |
getPathFromMain(...paths) |
Path inside the built main directory. |
getPathFromPreload(...paths) |
Path inside the built preload directory. |
getPathFromPublic(...paths) |
Path inside public in dev or renderer output in production. |
| Function | Description |
|---|---|
getAppVersion() |
Current app version. In dev, returns the entry version. |
getEntryVersion() |
Version from Electron app metadata. |
| Function | Description |
|---|---|
requireNative<T>(moduleName) |
Load CommonJS native helper from app.asar. |
importNative<T>(moduleName) |
Import ES module native helper from app.asar. |
| Function | Description |
|---|---|
restartApp() |
Restart the Electron app. |
singleInstance(window?) |
Restore and focus window on second-instance. |
setPortableDataPath(dirName?, create?) |
Store user data beside the executable. |
setAppUserModelId(id?) |
Set the Windows app user model ID. |
| Function | Description |
|---|---|
loadPage(win, htmlFilePath?) |
Load VITE_DEV_SERVER_URL in dev or renderer HTML in production. |
beautifyDevTools(win, options) |
Inject custom CSS/JS into DevTools. |
| Constant | Value |
|---|---|
isDev |
boolean — compile-time dev check. |
isWin |
boolean — process.platform === 'win32'. |
isMac |
boolean — process.platform === 'darwin'. |
isLinux |
boolean — process.platform === 'linux'. |
| Function | Description |
|---|---|
handleUnexpectedErrors(callback) |
Register a handler for uncaught errors. |
| Function | Signature |
|---|---|
hashBuffer |
(data: string | Buffer, length: number) => Buffer |
aesEncrypt |
(plainText: string, key: Buffer, iv: Buffer) => string |
aesDecrypt |
(encryptedText: string, key: Buffer, iv: Buffer) => string |
defaultSignature |
(buffer: Buffer, privateKey: string, cert: string, version: string) => string |
defaultVerifySignature |
(buffer: Buffer, version: string, signature: string, cert: string) => boolean |
| Function | Signature |
|---|---|
defaultCompressFile |
(buffer: Buffer) => Promise<Buffer> |
defaultDecompressFile |
(buffer: Buffer) => Promise<Buffer> |
| Function | Signature |
|---|---|
defaultDownloadText |
(url: string, headers: Record<string, any>, signal: AbortSignal, resolveData: ResolveDataFn) => Promise<T> |
defaultDownloadUpdateJSON |
(url: string, headers: Record<string, any>, signal: AbortSignal) => Promise<UpdateJSON> |
defaultDownloadAsar |
(url: string, headers: Record<string, any>, signal: AbortSignal, onDownloading?: (progress: DownloadingInfo) => void) => Promise<Buffer> |
getHeader |
(headers: Record<string, Arrayable<string>>, key: any) => any |
| Function | Signature | Description |
|---|---|---|
parseVersion |
(version: string) => Version |
Parse a version string into components. |
defaultIsLowerVersion |
(oldVer: string, newVer: string) => boolean |
Default version comparator. |
isUpdateJSON |
(json: object) => json is UpdateJSON |
Type guard for update JSON. |
defaultVersionJsonGenerator |
(existingJson: UpdateJSON, signature: string, version: string, minimumVersion: string) => UpdateJSON |
Generate version.json with signatures. |
Version
interface Version {
major: number
minor: number
patch: number
stage: string
stageVersion: number
}