Skip to content

Latest commit

 

History

History
1690 lines (1431 loc) · 37.3 KB

API.md

File metadata and controls

1690 lines (1431 loc) · 37.3 KB

API Reference

📖 For tutorials, quick start, and conceptual guides, see README.md.

Contents

The AUTO-GENERATED sections contain one source-derived TypeScript declaration with its JSDoc for each exported API. The short sections between them explain which API to use without repeating those declarations.


Entry API

Import from electron-incremental-update:

import { createElectronApp, startupWithUpdater, autoUpdate } from 'electron-incremental-update'

AppOption

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
}

startupWithUpdater

/**
 * Utils to startup with updater
 * @param fn startup function
 * @example
 * // in electron/main/index.ts
 * export default startupWithUpdater((updater) => {
 *   updater.checkUpdate()
 * })
 */
export function startupWithUpdater(
  fn: (updater: Updater) => Promisable<void>,
): (updater: Updater) => Promisable<void> { /* ... */ }

createElectronApp

/**
 * Initialize Electron with updater
 * @example
 * createElectronApp({
 *   updater: {
 *     provider: new GitHubProvider({
 *       username: 'yourname',
 *       repo: 'electron',
 *     }),
 *   },
 *   beforeStart(mainFilePath, logger) {
 *     logger?.debug(mainFilePath)
 *   },
 * })
 */
export async function createElectronApp(appOptions: AppOption = {}): Promise<void> { /* ... */ }

UpdaterErrorCode

export type UpdaterErrorCode = 'ERR_DOWNLOAD' | 'ERR_VALIDATE' | 'ERR_PARAM' | 'ERR_NETWORK'

UpdaterUnavailableCode

export type UpdaterUnavailableCode = 'UNAVAILABLE_ERROR' | 'UNAVAILABLE_DEV' | 'UNAVAILABLE_VERSION'

Logger

export interface Logger {
  info: (msg: string) => void
  debug: (msg: string) => void
  warn: (msg: string) => void
  error: (msg: string, e?: unknown) => void
}

UpdaterOption

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
}

UpdateInfoWithExtraVersion

/**
 * Update info with current app version and entry version
 */
export type UpdateInfoWithExtraVersion = UpdateInfo & {
  /**
   * Current app version
   */
  appVersion: string
  /**
   * Current entry version
   */
  entryVersion: string
}

autoUpdate

/**
 * Auto check update, download and install
 */
export async function autoUpdate(updater: Updater): Promise<void> { /* ... */ }

Runtime flow

The generated reference above is the source of truth for signatures and option types. The usual runtime flow is:

  1. Call createElectronApp() from the Electron entry process. It installs a verified pending asar, loads the configured main file, and initializes the updater.
  2. Export startupWithUpdater() from the real main process when startup code needs the Updater instance.
  3. Call updater.checkForUpdates(), then updater.downloadUpdate(), and finally updater.quitAndInstall() when an update is ready.
  4. Use autoUpdate(updater) when the default check-download-install sequence is sufficient.

The updater emits update-available, update-not-available, download-progress, update-downloaded, update-cancelled, and error. Use the generated Updater, UpdaterOption, and error-code definitions above for exact payloads.


Provider API

Import from electron-incremental-update/provider:

import {
  GitHubProvider,
  GitHubAtomProvider,
  GitHubApiProvider,
  LocalDevProvider,
} from 'electron-incremental-update/provider'

getHeader

/**
 * Safe get value from header
 * @param headers response header
 * @param key target header key
 */
export function getHeader(headers: Record<string, Arrayable<string>>, key: any): any { /* ... */ }

defaultDownloadText

/**
 * Default function to download json and parse to UpdateJson
 * @param url target url
 * @param headers extra headers
 * @param signal abort signal
 * @param resolveData on resolve
 */
export async function defaultDownloadText<T>(
  url: string,
  headers: Record<string, any>,
  signal: AbortSignal,
  resolveData: ResolveDataFn,
): Promise<T> { /* ... */ }

defaultDownloadUpdateJSON

/**
 * Default function to download json and parse to UpdateJson
 * @param url target url
 * @param headers extra headers
 * @param signal abort signal
 */
export async function defaultDownloadUpdateJSON(
  url: string,
  headers: Record<string, any>,
  signal: AbortSignal,
): Promise<UpdateJSON> { /* ... */ }

defaultDownloadAsar

/**
 * Default function to download asar buffer,
 * get total size from `Content-Length` header
 * @param url target url
 * @param headers extra headers
 * @param signal abort signal
 * @param onDownloading on downloading callback
 */
export async function defaultDownloadAsar(
  url: string,
  headers: Record<string, any>,
  signal: AbortSignal,
  onDownloading?: (progress: DownloadingInfo) => void,
): Promise<Buffer> { /* ... */ }

LocalDevProviderOptions

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
}

LocalDevProvider

/**
 * Update Provider for local development
 * - download update json from `{baseDir}/{versionPath}`
 * - download update asar from `{baseDir}/{name}-{version}.asar.br`
 *
 * This provider is useful for testing updates during development without
 * needing to deploy to a remote server.
 * @param options provider options
 */
export class LocalDevProvider extends BaseProvider { /* ... */ }

UpdateInfoWithURL

export type UpdateInfoWithURL = UpdateInfo & { url: string }

DownloadingInfo

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
}

VersionJSON

export type VersionJSON = UpdateInfoWithURL & { beta: UpdateInfoWithURL }

IProvider

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>
}

URLHandler

/**
 * Custom URL handler for GitHub provider, useful for mirrors and custom gateways
 * @param url original URL
 * @example
 * (url) => {
 *   url.hostname = 'mirror.ghproxy.com'
 *   url.pathname = 'https://github.com' + url.pathname
 *   return url
 * }
 */
export type URLHandler = (url: URL) => Promisable<URL | string | undefined | null>

GitHubApiProviderOptions

export interface GitHubApiProviderOptions extends BaseGitHubProviderOptions {
  token?: string
}

GitHubApiProvider

/**
 * 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 `urlHandler` in options to modify url before request
 * @param options provider options
 */
export class GitHubApiProvider extends BaseGitHubProvider<GitHubApiProviderOptions> { /* ... */ }

GitHubAtomProvider

/**
 * 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.br`
 *
 * you can setup `urlHandler` in options to modify url before request
 * @param options provider options
 */
export class GitHubAtomProvider extends BaseGitHubProvider { /* ... */ }

BaseGitHubProviderOptions

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
}

GitHubProviderOptions

export interface GitHubProviderOptions extends BaseGitHubProviderOptions {
  /**
   * Github branch name that fetch version
   * @default 'HEAD'
   */
  branch?: string
}

GitHubProvider

/**
 * 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.br`
 *
 * you can setup `urlHandler` in options to modify url before request
 * @param options provider options
 */
export class GitHubProvider extends BaseGitHubProvider<GitHubProviderOptions> { /* ... */ }

Provider selection

All providers implement IProvider, which supplies update JSON, compressed asar downloads, decompression, version comparison, and signature verification. The generated section above contains the exact contract and option types.

  • GitHubProvider reads version.json from a branch and downloads release assets from GitHub.
  • GitHubAtomProvider discovers the latest release through GitHub's Atom feed.
  • GitHubApiProvider uses the GitHub Releases API and supports an optional token.
  • LocalDevProvider reads the same update files from disk for local testing; prefer localDevUpdate: true in the Vite plugin when possible.

GitHub providers accept urlHandler when requests must go through a mirror or custom gateway:

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
  },
})

LocalDevProvider reads {baseDir}/{versionPath} and {baseDir}/{name}-{version}.asar.br. Its chunkSize and chunkDelay options only control simulated local download progress.


Vite Plugin API

Import from electron-incremental-update/vite:

import { electronWithUpdater, defineElectronConfig } from 'electron-incremental-update/vite'

Plugin Options

electronWithUpdater() accepts the process entries plus optional build and update settings. The generated ElectronWithUpdaterOptions reference below is the exact type definition; the common configuration shape is:

electronWithUpdater({
  entry: {
    files: './electron/entry.ts',
    asarOptions: {
      unpack: '**/*.node',
    },
  },
  main: { files: './electron/main.ts' },
  updater: {
    paths: {
      asarOutputPath: 'release/app.asar',
      compressedPath: 'release/app-1.0.0.asar.br',
    },
  },
})

entry.asarOptions is passed to @electron/asar when app.asar is created. Use unpack or unpackDir for native modules, ordering for deterministic file order, and the remaining CreateOptions fields for advanced packaging behavior. The same options are used by the local development update flow.

filterErrorMessageStartup

/**
 * Filter error messages from stdout/stderr during startup
 * @param args - Startup arguments
 * @param filter - Filter function to determine which messages to show
 */
export async function filterErrorMessageStartup(filter: (msg: string) => boolean): Promise<void> { /* ... */ }

fixWinCharEncoding

/**
 * Fix Windows character encoding by setting code page to UTF-8
 * @param fn - Function to wrap with encoding fix
 * @returns Wrapped function with Windows encoding fix
 */
export function fixWinCharEncoding<T extends AnyFunction>(fn: T): T { /* ... */ }

electronWithUpdater

/**
 * Base on `vite-plugin-electron/multi-env`
 * - integrate with updater
 * - no `renderer` config
 * - 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.electronDistPath` instead)
 *
 * @example
 * ```ts
 * 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
 *         }
 *       }),
 *     ],
 *   }
 * })
 * ```
 */
export async function electronWithUpdater(
  options: ElectronWithUpdaterOptions,
): Promise<Plugin[] | undefined> { /* ... */ }

ElectronViteHelperOptions

export interface ElectronViteHelperOptions extends ElectronWithUpdaterOptions {
  /**
   * Root dir of project
   * @default process.cwd()
   */
  root?: string
  /**
   * Config for renderer process
   */
  renderer?: Omit<UserConfig, 'root'>
}

defineElectronConfig

/**
 * Vite config helper
 * @see {@link electronWithUpdater}
 * @example
 * ```ts
 * 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: []
 *   }
 * })
 * ```
 */
export function defineElectronConfig(options: ElectronViteHelperOptions): UserConfig { /* ... */ }

PKG

export interface PKG {
  name: string
  version: string
  main: string
  type?: 'commonjs' | 'module'
  dependencies?: Record<string, string>
}

CommonBuildOption

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
        }
      }
    }
  }
}

ElectronWithUpdaterOptions

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: {
    /**
     * Options passed to `@electron/asar` when creating the app.asar archive
     */
    asarOptions?: CreateOptions
    /**
     * 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
}

LocalDevUpdateOptions

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
}

UpdaterOptions

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
}

GeneratorOverrideFunctions

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>
}

BuildAsarOptions

export interface BuildAsarOptions extends Required<
  Pick<
    NonNullable<UpdaterOptions['paths']>,
    'asarOutputPath' | 'electronDistPath' | 'compressedPath' | 'rendererDistPath'
  >
> {
  version: string
  asarOptions?: CreateOptions
  generateCompressedFile: NonNullable<GeneratorOverrideFunctions['generateCompressedFile']>
}

BuildVersionOptions

export interface BuildVersionOptions {
  version: string
  minimumVersion: string
  privateKey: string
  cert: string
  versionPath: string
  generateSignature: NonNullable<GeneratorOverrideFunctions['generateSignature']>
  generateUpdateJson: NonNullable<GeneratorOverrideFunctions['generateUpdateJson']>
}

All option types are auto-generated from JSDoc in the source code. See the sections above for ElectronWithUpdaterOptions, CommonBuildOption, UpdaterOptions, LocalDevUpdateOptions, BytecodeOptions, ElectronViteHelperOptions, etc.


Utilities API

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'

defaultSignature

/**
 * Default function to generate asar signature, returns generated signature
 * @param buffer file buffer
 * @param privateKey primary key
 * @param cert certificate
 * @param version target version
 */
export function defaultSignature(
  buffer: Buffer,
  privateKey: string,
  cert: string,
  version: string,
): string { /* ... */ }

defaultVerifySignature

/**
 * Default function to 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 function defaultVerifySignature(
  buffer: Buffer,
  version: string,
  signature: string,
  cert: string,
): boolean { /* ... */ }

getHeader

/**
 * Safe get value from header
 * @param headers response header
 * @param key target header key
 */
export function getHeader(headers: Record<string, Arrayable<string>>, key: any): any { /* ... */ }

defaultDownloadText

/**
 * Default function to download json and parse to UpdateJson
 * @param url target url
 * @param headers extra headers
 * @param signal abort signal
 * @param resolveData on resolve
 */
export async function defaultDownloadText<T>(
  url: string,
  headers: Record<string, any>,
  signal: AbortSignal,
  resolveData: ResolveDataFn,
): Promise<T> { /* ... */ }

defaultDownloadUpdateJSON

/**
 * Default function to download json and parse to UpdateJson
 * @param url target url
 * @param headers extra headers
 * @param signal abort signal
 */
export async function defaultDownloadUpdateJSON(
  url: string,
  headers: Record<string, any>,
  signal: AbortSignal,
): Promise<UpdateJSON> { /* ... */ }

defaultDownloadAsar

/**
 * Default function to download asar buffer,
 * get total size from `Content-Length` header
 * @param url target url
 * @param headers extra headers
 * @param signal abort signal
 * @param onDownloading on downloading callback
 */
export async function defaultDownloadAsar(
  url: string,
  headers: Record<string, any>,
  signal: AbortSignal,
  onDownloading?: (progress: DownloadingInfo) => void,
): Promise<Buffer> { /* ... */ }

isDev

/**
 * Compile time dev check
 */
export const isDev = __EIU_IS_DEV__

getPathFromAppNameAsar

/**
 * 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 { /* ... */ }

getAppVersion

/**
 * Get app version, if is in dev, return `getEntryVersion()`
 */
export function getAppVersion(): string { /* ... */ }

getEntryVersion

/**
 * Get entry version
 */
export function getEntryVersion(): string { /* ... */ }

requireNative

/**
 * Use `require` to load native module from entry asar
 * @param moduleName file name in entry
 * @example
 * requireNative<typeof import('../native/db')>('db')
 */
export function requireNative<T = any>(moduleName: string): T { /* ... */ }

importNative

/**
 * Use `import` to load native module from entry asar
 * @param moduleName file name in entry
 * @example
 * await importNative<typeof import('../native/db')>('db')
 */
export async function importNative<T = any>(moduleName: string): Promise<T> { /* ... */ }

restartApp

/**
 * Restarts the Electron app.
 */
export function restartApp(): void { /* ... */ }

setAppUserModelId

/**
 * Fix app use model id, only for Windows
 * @param id app id, default is `org.${electron.app.name}`
 */
export function setAppUserModelId(id?: string): void { /* ... */ }

disableHWAccForWin7

/**
 * Disable hardware acceleration for Windows 7
 *
 * Only support CommonJS
 */
export function disableHWAccForWin7(): void { /* ... */ }

singleInstance

/**
 * Keep single electron instance and auto restore window on `second-instance` event
 * @param window brwoser window to show
 */
export function singleInstance(window?: BrowserWindow): void { /* ... */ }

setPortableDataPath

/**
 * Set `userData` dir to the dir of .exe file
 *
 * Useful for portable Windows app
 * @param dirName dir name, default to `data`
 * @param create whether to create dir, default to `true`
 */
export function setPortableDataPath(dirName: string = 'data', create: boolean = true): void { /* ... */ }

loadPage

/**
 * Load `process.env.VITE_DEV_SERVER_URL` when dev, else load html file
 * @param win window
 * @param htmlFilePath html file path, default is `index.html`
 */
export function loadPage(win: BrowserWindow, htmlFilePath = 'index.html'): void { /* ... */ }

beautifyDevTools

/**
 * Beautify devtools' font and scrollbar
 * @param win target window
 * @param options sans font family, mono font family and scrollbar
 * @see https://github.com/electron/electron/issues/42055
 */
export function beautifyDevTools(win: BrowserWindow, options: BeautifyDevToolsOptions): void { /* ... */ }

getPathFromMain

/**
 * Get joined path from main dir
 * @param paths rest paths
 */
export function getPathFromMain(...paths: string[]): string { /* ... */ }

getPathFromPreload

/**
 * Get joined path from preload dir
 * @param paths rest paths
 */
export function getPathFromPreload(...paths: string[]): string { /* ... */ }

getPathFromPublic

/**
 * Get joined path from publich dir
 * @param paths rest paths
 */
export function getPathFromPublic(...paths: string[]): string { /* ... */ }

getPathFromEntryAsar

/**
 * Get joined path from entry asar
 * @param paths rest paths
 */
export function getPathFromEntryAsar(...paths: string[]): string { /* ... */ }

handleUnexpectedErrors

/**
 * Handle all unhandled error
 * @param callback callback function
 */
export function handleUnexpectedErrors(callback: (err: unknown) => void): void { /* ... */ }

Version

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
}

parseVersion

/**
 * Parse version string to {@link 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.
 * @param version version string
 */
export function parseVersion(version: string): Version { /* ... */ }

defaultIsLowerVersion

/**
 * Default function to check the old version is less than new version
 * @param oldVer old version string
 * @param newVer new version string
 */
export function defaultIsLowerVersion(oldVer: string, newVer: string): boolean { /* ... */ }

UpdateInfo

/**
 * Update info json
 */
export interface UpdateInfo {
  /**
   * Update Asar signature
   */
  signature: string
  /**
   * Minimum version
   */
  minimumVersion: string
  /**
   * Target version
   */
  version: string
}

UpdateJSON

/**
 * {@link UpdateInfo} with beta
 */
export type UpdateJSON = UpdateInfo & {
  /**
   * Beta update info
   */
  beta: UpdateInfo
}

isUpdateJSON

/**
 * Check is `UpdateJSON`
 * @param json any variable
 */
export function isUpdateJSON(json: object): json is UpdateJSON { /* ... */ }

defaultVersionJsonGenerator

/**
 * Default function to generate `UpdateJSON`
 * @param existingJson exising update json
 * @param signature sigature
 * @param version target version
 * @param minimumVersion minimum version
 */
export function defaultVersionJsonGenerator(
  existingJson: UpdateJSON,
  signature: string,
  version: string,
  minimumVersion: string,
): UpdateJSON { /* ... */ }

defaultCompressFile

/**
 * Default function to compress file using brotli
 * @param buffer uncompressed file buffer
 */
export async function defaultCompressFile(buffer: Buffer): Promise<Buffer> { /* ... */ }

defaultDecompressFile

/**
 * Default function to decompress file using brotli
 * @param buffer compressed file buffer
 */
export async function defaultDecompressFile(buffer: Buffer): Promise<Buffer> { /* ... */ }

Utility map

The generated reference above is grouped by export order. Use this map to jump to the relevant family:

  • Paths: getPathFromAppNameAsar, getPathFromEntryAsar, getPathFromMain, getPathFromPreload, and getPathFromPublic resolve packaged and development paths.
  • Versions: getAppVersion, getEntryVersion, parseVersion, and defaultIsLowerVersion read and compare versions.
  • Native modules: requireNative and importNative load native helpers from the entry asar.
  • App lifecycle: restartApp, singleInstance, setPortableDataPath, setAppUserModelId, and handleUnexpectedErrors control process behavior.
  • Windows and UI: loadPage, beautifyDevTools, and disableHWAccForWin7 cover renderer startup and platform-specific setup.
  • Update transport: defaultDownloadText, defaultDownloadUpdateJSON, defaultDownloadAsar, and getHeader handle downloads.
  • Integrity and compression: hashBuffer, aesEncrypt, aesDecrypt, defaultSignature, defaultVerifySignature, defaultCompressFile, and defaultDecompressFile support update packaging.