diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 0a4c774..191401b 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -31,9 +31,12 @@ jobs:
- name: Setup Volta
uses: volta-cli/action@v4.2.1
- - name: Install dependencies
+ - name: Install third party dependencies
run: npm ci
+ - name: Check for third party vulnerabilities
+ run: npm audit
+
- name: Check for linting errors
run: npm run lint
diff --git a/.gitignore b/.gitignore
index 77fb328..8ed43ec 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,5 @@ cache
tests/fixtures/releases/app-0.0.1-linux-x64
tests/fixtures/app-current/updater.js
+tests/fixtures/app-latest
+tests/fixtures/nwjs-user-data
diff --git a/LICENSE b/LICENSE
index 53298f1..c918d8b 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2023 NW.js Utils
+Copyright (c) 2026 NW.js Utils
Copyright (c) 2014 Eldar Djafarov
Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/README.md b/README.md
index b165f6b..72ada51 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,33 @@ Update NW.js applications for Linux, MacOS and Windows platforms.
## Usage
```js
-import {}
+import Updater from "@nwutils/updater";
+
+const updater = new Updater(nw.App.manifest);
+
+let updateStatus = "";
+let newManifest = "";
+updater.checkNewVersion((err, newerVersionExists, remoteManifest) => {
+ if (err) {
+ updateStatus = `Error checking for updates: ${err.message}`;
+ return;
+ }
+ if (newerVersionExists) {
+ updateStatus = "A newer version is available.";
+ newManifest = remoteManifest;
+ } else {
+ updateStatus = "No new version available.";
+ }
+});
+
+let downloadStatus = "";
+updater.download((err, filePath) => {
+ if (err) {
+ downloadStatus = `Error downloading update: ${err.message}`;
+ return;
+ }
+ downloadStatus = "Update downloaded successfully at " + filePath;
+}, newManifest);
```
It gives you low-level API to:
@@ -26,19 +52,12 @@ It gives you low-level API to:
5. The new app (in temp) will copy itself to the original folder, overwriting the old app.
6. The new app will run itself from original folder and exit the process.
-You should build this logic by yourself though. As a reference you can use [example](app/index.html).
-
-Covered by tests and works for [linux](http://screencast.com/t/Je2ptbHhP), [windows](http://screencast.com/t/MSTKqVS3) and [mac](http://screencast.com/t/OXyC5xoA).
-
-## Examples
-
-- [Basic](examples/basic.js)
-
-
## API
+
#### new updater(manifest, options)
+
Creates new instance of updater. Manifest could be a `package.json` of project.
Note that compressed apps are assumed to be downloaded in the format produced by [nw-builder](https://github.com/nwutils/nw-builder) (or [grunt-nw-builder](https://github.com/nwjs/grunt-nw-builder)).
@@ -49,7 +68,9 @@ Note that compressed apps are assumed to be downloaded in the format produced by
- options `object` - Optional
+
#### updater.checkNewVersion(cb)
+
Will check the latest available version of the application by requesting the manifest specified in `manifestUrl`.
The callback will always be called; the second parameter indicates whether or not there's a newer version.
@@ -60,8 +81,10 @@ This function assumes you use [Semantic Versioning](http://semver.org) and enfor
- cb `function` - Callback arguments: error, newerVersionExists (`Boolean`), remoteManifest
+
#### updater.download(cb, newManifest)
-Downloads the new app to a template folder
+
+Downloads the new app to a temporary folder.
**Params**
@@ -70,17 +93,23 @@ Downloads the new app to a template folder
**Returns**: `Request` - Request - stream, the stream contains `manifest` property with new manifest and 'content-length' property with the size of package.
+
#### updater.getAppPath()
+
Returns executed application path
**Returns**: `string`
+
#### updater.getAppExec()
+
Returns current application executable
**Returns**: `string`
+
#### updater.unpack(filename, cb, manifest)
+
Will unpack the `filename` in temporary folder.
For Windows, [unzip](https://www.mkssoftware.com/docs/man1/unzip.1.asp) is used (which is [not signed](https://github.com/edjafarov/node-webkit-updater/issues/68)).
@@ -91,7 +120,9 @@ For Windows, [unzip](https://www.mkssoftware.com/docs/man1/unzip.1.asp) is used
- manifest `object`
+
#### updater.runInstaller(appPath, args, options)
+
Runs installer
**Params**
@@ -102,7 +133,9 @@ Runs installer
**Returns**: `function`
+
#### updater.install(copyPath, cb)
+
Installs the app (copies current application to `copyPath`)
**Params**
@@ -111,7 +144,9 @@ Installs the app (copies current application to `copyPath`)
- cb `function` - Callback arguments: error
+
#### updater.run(execPath, args, options)
+
Runs the app from original app executable path.
**Params**
@@ -122,7 +157,6 @@ Runs the app from original app executable path.
Note: if this doesn't work, try `gui.Shell.openItem(execPath)` (see [node-webkit Shell](https://github.com/rogerwang/node-webkit/wiki/Shell)).
-
---
## Manifest Schema
@@ -156,18 +190,23 @@ The manifest could be a `package.json` of project, but doesn't have to be.
The name of your app. From time, it is assumed your Mac app is called `.app`, your Windows executable is `.exe`, etc.
### manifest.version
+
[semver](http://semver.org) version of your app.
### manifest.manifestUrl
+
The URL where your latest manifest is hosted; where node-webkit-updater looks to check if there is a newer version of your app available.
### manifest.packages
+
An "object" containing an object for each OS your app (at least this version of your app) supports; `mac`, `win`, `linux32`, `linux64`.
### manifest.packages.{mac, win, linux32, linux64}.url
+
Each package has to contain a `url` property pointing to where the app (for the version & OS in question) can be downloaded.
### manifest.packages.{mac, win, linux32, linux64}.execPath (Optional)
+
It's assumed your app is stored at the root of your package, use this to override that and specify a path (relative to the root of your package).
This can also be used to override `manifest.name`; e.g. if your `manifest.name` is `helloWorld` (therefore `helloWorld.app` on Mac) but your Windows executable is named `nw.exe`. Then you'd set `execPath` to `nw.exe`
@@ -177,9 +216,11 @@ This can also be used to override `manifest.name`; e.g. if your `manifest.name`
## Troubleshooting
### Mac
+
If you get an error on Mac about too many files being open, run `ulimit -n 10240`
### Windows
+
On Windows, there is no "unzip" command built in by default. As a result, this project uses a third party "unzip.exe" in order to extract the downloaded update. On the NWJS site, in the "How to package and distribute your apps" file, one of the recommended methods of distribution is using EnigmaVirtualBox to package the app, nw.exe, and required DLLs into a single EXE file. This method works great for distribution, but unfortunately breaks node-webkit-updater, because it wraps the required unzip.exe file inside of the created EnigmaVirtualBox EXE. As a result, *it is not possible to use EnigmaVirtualBox to distribute your app if you plan on using node-webkit-updater*. Try using InnoSetup instead.
## Contributing
diff --git a/package-lock.json b/package-lock.json
index b232b1f..7606aa8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -882,6 +882,16 @@
"url": "https://opencollective.com/express"
}
},
+ "node_modules/brace-expansion": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz",
+ "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
"node_modules/braces": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
@@ -1935,9 +1945,9 @@
}
},
"node_modules/lodash": {
- "version": "4.17.21",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
- "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "version": "4.18.1",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz",
+ "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==",
"dev": true,
"license": "MIT"
},
@@ -2032,6 +2042,19 @@
"url": "https://opencollective.com/express"
}
},
+ "node_modules/minimatch": {
+ "version": "5.1.9",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz",
+ "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/minipass": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz",
@@ -2727,29 +2750,6 @@
"minimatch": "^5.1.0"
}
},
- "node_modules/readdir-glob/node_modules/brace-expansion": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
- "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0"
- }
- },
- "node_modules/readdir-glob/node_modules/minimatch": {
- "version": "5.1.6",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
- "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^2.0.1"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/resedit": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/resedit/-/resedit-3.0.2.tgz",
diff --git a/src/main.js b/src/main.js
index c1710aa..749691c 100644
--- a/src/main.js
+++ b/src/main.js
@@ -1,4 +1,7 @@
+const fs = await import('node:fs');
const os = await import('node:os');
+const path = await import('node:path');
+const stream = await import('node:stream');
function semverGt(v1, v2) {
const [major1, minor1, patch1] = v1.replace(/^v/i, '').split('.').map(Number);
@@ -40,6 +43,32 @@ function semverGt(v1, v2) {
* @property {string} temporaryDirectory - The path to a directory to download the updates to and unpack them in. Defaults to [`os.tmpdir()`](https://nodejs.org/api/os.html#os_os_tmpdir)
*/
+function getHost() {
+ let platform;
+
+ switch (process.platform) {
+ case 'win32':
+ platform = 'windows';
+ break;
+
+ case 'darwin':
+ platform = 'macos';
+ break;
+
+ case 'linux':
+ platform = 'linux';
+ break;
+
+ default:
+ throw new Error(`Unsupported platform: ${process.platform}`);
+ }
+
+ const arch = process.arch;
+
+ return `${platform}-${arch}`;
+
+}
+
class Updater {
/**
@@ -83,6 +112,54 @@ class Updater {
cb(error, false, null);
});
}
+
+ /**
+ * Downloads the new app to a temporary folder.
+ *
+ * @async
+ * @method
+ * @param {(error: Error|null, filepath: string|null) => void} cb
+ * @param {Manifest} newManifest
+ * @returns {void}
+ */
+ download(cb, newManifest) {
+ const manifest = newManifest ?? this.manifest;
+ const url = manifest.packages[getHost()].url;
+
+ const filename = decodeURI(path.basename(url));
+
+ fs.mkdirSync(this.options.temporaryDirectory, { recursive: true });
+ const destinationPath = path.resolve(
+ this.options.temporaryDirectory,
+ filename
+ );
+
+ const writeStream = fs.createWriteStream(destinationPath);
+
+ fetch(url)
+ .then((response) => {
+ if (!response.ok) {
+ throw new Error(
+ `Failed to download update: ${response.status} ${response.statusText}`
+ );
+ }
+
+ if (!response.body) {
+ throw new Error('Response body is not readable');
+ }
+
+ return stream.promises.pipeline(
+ response.body,
+ writeStream
+ );
+ })
+ .then(() => {
+ cb(null, destinationPath);
+ })
+ .catch((err) => {
+ cb(err, null);
+ });
+ }
}
export default Updater;
diff --git a/tests/fixtures/app-current/index.html b/tests/fixtures/app-current/index.html
index 97d4e5d..02d2480 100644
--- a/tests/fixtures/app-current/index.html
+++ b/tests/fixtures/app-current/index.html
@@ -1,13 +1,42 @@
+
Demo
+
-
-
+
+
+
+
Function
+
Action
+
Status
+
Data
+
+
+
+
+
+
checkNewVersion
+
+
+
+
+
+
+
download
+
+
+
+
+
+
+
+
+
diff --git a/tests/fixtures/app-current/index.js b/tests/fixtures/app-current/index.js
index b06a155..18558a8 100644
--- a/tests/fixtures/app-current/index.js
+++ b/tests/fixtures/app-current/index.js
@@ -1,10 +1,13 @@
+const path = await import("node:path");
+const process = await import("node:process");
+
import Updater from "./updater.js";
-const manifest = nw.require("./package.json");
let updater;
document.addEventListener("DOMContentLoaded", () => {
- updater = new Updater(manifest);
+ updater = new Updater(nw.App.manifest, { temporaryDirectory: path.resolve(nw.App.dataPath, "tmpDir") });
document.getElementById("check-for-updates-button").addEventListener("click", handleCheckForUpdates);
+ document.getElementById("download-button").addEventListener("click", handleDownload);
});
function handleCheckForUpdates() {
@@ -17,8 +20,23 @@ function handleCheckForUpdates() {
}
if (newerVersionExists) {
updateStatus.textContent = "A newer version is available.";
+ document.getElementById("update-data").textContent = JSON.stringify(remoteManifest, null, 2);
} else {
updateStatus.textContent = "No new version available.";
}
});
}
+
+function handleDownload() {
+ const downloadStatus = document.getElementById("download-status");
+ const newManifest = document.getElementById("update-data").textContent ? JSON.parse(document.getElementById("update-data").textContent) : null;
+ downloadStatus.textContent = "Downloading update...";
+ updater.download((err, filePath) => {
+ if (err) {
+ downloadStatus.textContent = `Error downloading update: ${err.message}`;
+ return;
+ }
+ downloadStatus.textContent = "Update downloaded successfully at " + filePath;
+ document.getElementById("download-data").textContent = filePath;
+ }, newManifest);
+}
diff --git a/tests/fixtures/app-latest/index.html b/tests/fixtures/app-latest/index.html
deleted file mode 100644
index 97d4e5d..0000000
--- a/tests/fixtures/app-latest/index.html
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
- Demo
-
-
-
-
-
-
-
diff --git a/tests/fixtures/app-latest/index.js b/tests/fixtures/app-latest/index.js
deleted file mode 100644
index b06a155..0000000
--- a/tests/fixtures/app-latest/index.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import Updater from "./updater.js";
-const manifest = nw.require("./package.json");
-
-let updater;
-document.addEventListener("DOMContentLoaded", () => {
- updater = new Updater(manifest);
- document.getElementById("check-for-updates-button").addEventListener("click", handleCheckForUpdates);
-});
-
-function handleCheckForUpdates() {
- const updateStatus = document.getElementById("update-status");
- updateStatus.textContent = "Checking for updates...";
- updater.checkNewVersion((err, newerVersionExists, remoteManifest) => {
- if (err) {
- updateStatus.textContent = `Error checking for updates: ${err.message}`;
- return;
- }
- if (newerVersionExists) {
- updateStatus.textContent = "A newer version is available.";
- } else {
- updateStatus.textContent = "No new version available.";
- }
- });
-}
diff --git a/tests/fixtures/app-latest/package.json b/tests/fixtures/app-latest/package.json
deleted file mode 100644
index 4ccc516..0000000
--- a/tests/fixtures/app-latest/package.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "name": "demo",
- "version": "0.0.2",
- "main": "index.html",
- "chromium-args": "--enable-features=NWESM,NWChainImportNode",
- "author": "NW.js Utils ",
- "license": "MIT",
- "manifestUrl": "http://localhost:3000/manifest.json",
- "packages": {
- "linux-x64": {
- "url": "http://localhost:3000/app-0.0.1-linux-x64.zip"
- }
- }
-}
\ No newline at end of file
diff --git a/tests/fixtures/app-latest/updater.js b/tests/fixtures/app-latest/updater.js
deleted file mode 100644
index c1710aa..0000000
--- a/tests/fixtures/app-latest/updater.js
+++ /dev/null
@@ -1,88 +0,0 @@
-const os = await import('node:os');
-
-function semverGt(v1, v2) {
- const [major1, minor1, patch1] = v1.replace(/^v/i, '').split('.').map(Number);
- const [major2, minor2, patch2] = v2.replace(/^v/i, '').split('.').map(Number);
-
- if (major1 !== major2) {
- return major1 > major2;
- }
- if (minor1 !== minor2) {
- return minor1 > minor2;
- }
- return patch1 > patch2;
-}
-
-/**
- * @typedef {object} Platform
- * @property {string} url - The URL to the package
- * @property {string} execPath - The path to the executable
- */
-
-/**
- * @typedef {object} Packages
- * @property {Platform} win - The Windows package
- * @property {Platform} mac - The macOS package
- * @property {Platform} linux32 - The Linux 32-bit package
- * @property {Platform} linux64 - The Linux 64-bit package
- */
-
-/**
- * @typedef {object} Manifest
- * @property {string} name - The name of the application
- * @property {string} version - The current version of the application
- * @property {string} manifestUrl - The URL to the remote manifest file
- * @property {Packages} packages - The packages for the application
- */
-
-/**
- * @typedef {object} UpdaterOptions
- * @property {string} temporaryDirectory - The path to a directory to download the updates to and unpack them in. Defaults to [`os.tmpdir()`](https://nodejs.org/api/os.html#os_os_tmpdir)
- */
-
-class Updater {
-
- /**
- * Creates new instance of Updater.
- *
- * @constructor
- * @param {Manifest} manifest - See the [manifest schema](https://github.com/nwutils/updater?tab=readme-ov-file#manifest-schema).
- * @param {UpdaterOptions} options - Optional
- */
- constructor(manifest, options) {
- this.manifest = manifest;
- this.options = {
- temporaryDirectory: options && options.temporaryDirectory || os.tmpdir(),
- };
- }
-
- /**
- * Check the latest available version of the application by requesting the manifest specified in `manifestUrl`.
- *
- * @async
- * @method
- * @param {(error: Error|null, newerVersionExists: boolean, remoteManifest: object|null) => void} cb
- * @returns {void}
- */
- checkNewVersion(cb) {
- const currentVersion = this.manifest.version;
-
- fetch(this.manifest.manifestUrl)
- .then((response) => {
- if (!response.ok) {
- throw new Error(`HTTP error: ${response.status}`);
- }
- return response.json();
- })
- .then((data) => {
- const latestVersion = data.version;
-
- cb(null, semverGt(latestVersion, currentVersion), data);
- })
- .catch((error) => {
- cb(error, false, null);
- });
- }
-}
-
-export default Updater;
diff --git a/tests/fixtures/releases/manifest.json b/tests/fixtures/releases/manifest.json
index fe9c30e..524c8d5 100644
--- a/tests/fixtures/releases/manifest.json
+++ b/tests/fixtures/releases/manifest.json
@@ -2,10 +2,10 @@
"name": "app",
"version": "0.0.2",
"author": "NW.js Utils",
- "manifestUrl": "http://localhost:3000/releases/manifest.json",
+ "manifestUrl": "http://localhost:3000/manifest.json",
"packages": {
"linux-x64": {
- "url": "http://localhost:3000/releases/app-0.0.2-linux-x64.zip"
+ "url": "http://localhost:3000/app-0.0.2-linux-x64.zip"
}
}
}
diff --git a/tests/specs/main.test.js b/tests/specs/main.test.js
index e28457e..6b636ce 100644
--- a/tests/specs/main.test.js
+++ b/tests/specs/main.test.js
@@ -2,6 +2,7 @@ import assert from "node:assert/strict";
import fs from "node:fs";
import http from "node:http";
import path from "node:path";
+import os from "node:os";
import { after, before, describe, it } from "node:test";
import express from "express";
@@ -20,7 +21,8 @@ describe("updater test suite", function () {
let driver = undefined;
const options = new chrome.Options();
const seleniumArguments = [
- "nwapp=" + path.resolve("tests", "fixtures", "app-current")
+ "nwapp=" + path.resolve("tests", "fixtures", "app-current"),
+ "user-data-dir=" + path.resolve("tests", "fixtures", "nwjs-user-data"),
];
seleniumArguments.push("headless=new");
options.addArguments(seleniumArguments);
@@ -79,15 +81,26 @@ describe("updater test suite", function () {
const button = await driver.findElement(selenium.By.id("check-for-updates-button"));
await button.click();
- // const postButtonClick = await driver.findElement(statusLocator).getText();
- // await driver.sleep(1000);
- // assert.strictEqual(postButtonClick, "Checking for updates...");
-
- // await driver.sleep(5000);
const finalText = await driver.findElement(statusLocator).getText();
assert.strictEqual(finalText, "A newer version is available.");
});
+ it("runs the application and downloads the update", async function () {
+ const downloadLocator = selenium.By.id("download-status");
+ const initialText = await driver.findElement(downloadLocator).getText();
+ assert.strictEqual(initialText, "");
+
+ const button = await driver.findElement(selenium.By.id("download-button"));
+ await button.click();
+ await driver.sleep(5000);
+
+ const finalText = await driver.findElement(downloadLocator).getText();
+ assert.ok(finalText.startsWith("Update downloaded successfully"), "Expected download success message.");
+
+ const downloadFilePath = await driver.findElement(selenium.By.id("download-data")).getText();
+ assert.strictEqual(downloadFilePath, path.resolve(process.cwd(), "tests", "fixtures", "nwjs-user-data", "Default", "tmpDir", "app-0.0.2-linux-x64.zip"));
+ });
+
after(async function () {
await new Promise((resolve, reject) => {
server.close((err) => {
diff --git a/types/src/main.d.ts b/types/src/main.d.ts
index a54ac80..140325a 100644
--- a/types/src/main.d.ts
+++ b/types/src/main.d.ts
@@ -51,29 +51,6 @@ export type UpdaterOptions = {
*/
temporaryDirectory: string;
};
-/**
- * @typedef {object} Platform
- * @property {string} url - The URL to the package
- * @property {string} execPath - The path to the executable
- */
-/**
- * @typedef {object} Packages
- * @property {Platform} win - The Windows package
- * @property {Platform} mac - The macOS package
- * @property {Platform} linux32 - The Linux 32-bit package
- * @property {Platform} linux64 - The Linux 64-bit package
- */
-/**
- * @typedef {object} Manifest
- * @property {string} name - The name of the application
- * @property {string} version - The current version of the application
- * @property {string} manifestUrl - The URL to the remote manifest file
- * @property {Packages} packages - The packages for the application
- */
-/**
- * @typedef {object} UpdaterOptions
- * @property {string} temporaryDirectory - The path to a directory to download the updates to and unpack them in. Defaults to [`os.tmpdir()`](https://nodejs.org/api/os.html#os_os_tmpdir)
- */
declare class Updater {
/**
* Creates new instance of Updater.
@@ -96,4 +73,14 @@ declare class Updater {
* @returns {void}
*/
checkNewVersion(cb: (error: Error | null, newerVersionExists: boolean, remoteManifest: object | null) => void): void;
+ /**
+ * Downloads the new app to a temporary folder.
+ *
+ * @async
+ * @method
+ * @param {(error: Error|null, filepath: string|null) => void} cb
+ * @param {Manifest} newManifest
+ * @returns {void}
+ */
+ download(cb: (error: Error | null, filepath: string | null) => void, newManifest: Manifest): void;
}