electron-updater 4.3.5 → 4.3.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/out/AppAdapter.js +19 -28
- package/out/AppAdapter.js.map +1 -1
- package/out/AppImageUpdater.js +103 -173
- package/out/AppImageUpdater.js.map +1 -1
- package/out/AppUpdater.d.ts +1 -3
- package/out/AppUpdater.js +517 -773
- package/out/AppUpdater.js.map +1 -1
- package/out/BaseUpdater.js +79 -103
- package/out/BaseUpdater.js.map +1 -1
- package/out/DownloadedUpdateHelper.js +150 -224
- package/out/DownloadedUpdateHelper.js.map +1 -1
- package/out/ElectronAppAdapter.js +35 -63
- package/out/ElectronAppAdapter.js.map +1 -1
- package/out/MacUpdater.d.ts +1 -1
- package/out/MacUpdater.js +132 -182
- package/out/MacUpdater.js.map +1 -1
- package/out/NoOpLogger.d.ts +6 -0
- package/out/NoOpLogger.js +19 -0
- package/out/NoOpLogger.js.map +1 -0
- package/out/NsisUpdater.js +199 -331
- package/out/NsisUpdater.js.map +1 -1
- package/out/differentialDownloader/DataSplitter.js +180 -252
- package/out/differentialDownloader/DataSplitter.js.map +1 -1
- package/out/differentialDownloader/DifferentialDownloader.d.ts +3 -0
- package/out/differentialDownloader/DifferentialDownloader.js +243 -308
- package/out/differentialDownloader/DifferentialDownloader.js.map +1 -1
- package/out/differentialDownloader/FileWithEmbeddedBlockMapDifferentialDownloader.js +29 -65
- package/out/differentialDownloader/FileWithEmbeddedBlockMapDifferentialDownloader.js.map +1 -1
- package/out/differentialDownloader/GenericDifferentialDownloader.js +7 -21
- package/out/differentialDownloader/GenericDifferentialDownloader.js.map +1 -1
- package/out/differentialDownloader/ProgressDifferentialDownloadCallbackTransform.d.ts +32 -0
- package/out/differentialDownloader/ProgressDifferentialDownloadCallbackTransform.js +90 -0
- package/out/differentialDownloader/ProgressDifferentialDownloadCallbackTransform.js.map +1 -0
- package/out/differentialDownloader/downloadPlanBuilder.js +99 -124
- package/out/differentialDownloader/downloadPlanBuilder.js.map +1 -1
- package/out/differentialDownloader/multipleRangeDownloader.js +99 -148
- package/out/differentialDownloader/multipleRangeDownloader.js.map +1 -1
- package/out/electronHttpExecutor.js +73 -106
- package/out/electronHttpExecutor.js.map +1 -1
- package/out/event.d.ts +35 -0
- package/out/event.js +39 -0
- package/out/event.js.map +1 -0
- package/out/log.d.ts +11 -0
- package/out/log.js +19 -0
- package/out/log.js.map +1 -0
- package/out/main.d.ts +1 -4
- package/out/main.js +60 -212
- package/out/main.js.map +1 -1
- package/out/providerFactory.js +49 -105
- package/out/providerFactory.js.map +1 -1
- package/out/providers/BintrayProvider.d.ts +2 -2
- package/out/providers/BintrayProvider.js +40 -95
- package/out/providers/BintrayProvider.js.map +1 -1
- package/out/providers/GenericProvider.d.ts +2 -2
- package/out/providers/GenericProvider.js +46 -80
- package/out/providers/GenericProvider.js.map +1 -1
- package/out/providers/GitHubProvider.d.ts +2 -2
- package/out/providers/GitHubProvider.js +122 -201
- package/out/providers/GitHubProvider.js.map +1 -1
- package/out/providers/PrivateGitHubProvider.js +87 -165
- package/out/providers/PrivateGitHubProvider.js.map +1 -1
- package/out/providers/Provider.js +122 -173
- package/out/providers/Provider.js.map +1 -1
- package/out/util.d.ts +5 -0
- package/out/util.js +42 -0
- package/out/util.js.map +1 -0
- package/out/windowsExecutableCodeSignatureVerifier.js +99 -139
- package/out/windowsExecutableCodeSignatureVerifier.js.map +1 -1
- package/package.json +33 -31
package/out/AppUpdater.js
CHANGED
|
@@ -1,799 +1,543 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.NoOpLogger = exports.AppUpdater = void 0;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
const data = require("./ElectronAppAdapter");
|
|
102
|
-
|
|
103
|
-
_ElectronAppAdapter = function () {
|
|
104
|
-
return data;
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
return data;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
function _electronHttpExecutor() {
|
|
111
|
-
const data = require("./electronHttpExecutor");
|
|
112
|
-
|
|
113
|
-
_electronHttpExecutor = function () {
|
|
114
|
-
return data;
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
return data;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function _GenericProvider() {
|
|
121
|
-
const data = require("./providers/GenericProvider");
|
|
122
|
-
|
|
123
|
-
_GenericProvider = function () {
|
|
124
|
-
return data;
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
return data;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
function _main() {
|
|
131
|
-
const data = require("./main");
|
|
132
|
-
|
|
133
|
-
_main = function () {
|
|
134
|
-
return data;
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
return data;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
function _providerFactory() {
|
|
141
|
-
const data = require("./providerFactory");
|
|
142
|
-
|
|
143
|
-
_providerFactory = function () {
|
|
144
|
-
return data;
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
return data;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
|
|
151
|
-
|
|
152
|
-
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
153
|
-
|
|
154
|
-
class AppUpdater extends _events().EventEmitter {
|
|
155
|
-
constructor(options, app) {
|
|
156
|
-
super();
|
|
157
|
-
/**
|
|
158
|
-
* Whether to automatically download an update when it is found.
|
|
159
|
-
*/
|
|
160
|
-
|
|
161
|
-
this.autoDownload = true;
|
|
4
|
+
const builder_util_runtime_1 = require("builder-util-runtime");
|
|
5
|
+
const crypto_1 = require("crypto");
|
|
6
|
+
const events_1 = require("events");
|
|
7
|
+
const fs_extra_1 = require("fs-extra");
|
|
8
|
+
const js_yaml_1 = require("js-yaml");
|
|
9
|
+
const lazy_val_1 = require("lazy-val");
|
|
10
|
+
const path = require("path");
|
|
11
|
+
const semver_1 = require("semver");
|
|
12
|
+
const DownloadedUpdateHelper_1 = require("./DownloadedUpdateHelper");
|
|
13
|
+
const ElectronAppAdapter_1 = require("./ElectronAppAdapter");
|
|
14
|
+
const electronHttpExecutor_1 = require("./electronHttpExecutor");
|
|
15
|
+
const GenericProvider_1 = require("./providers/GenericProvider");
|
|
16
|
+
const main_1 = require("./main");
|
|
17
|
+
const providerFactory_1 = require("./providerFactory");
|
|
18
|
+
class AppUpdater extends events_1.EventEmitter {
|
|
19
|
+
constructor(options, app) {
|
|
20
|
+
super();
|
|
21
|
+
/**
|
|
22
|
+
* Whether to automatically download an update when it is found.
|
|
23
|
+
*/
|
|
24
|
+
this.autoDownload = true;
|
|
25
|
+
/**
|
|
26
|
+
* Whether to automatically install a downloaded update on app quit (if `quitAndInstall` was not called before).
|
|
27
|
+
*/
|
|
28
|
+
this.autoInstallOnAppQuit = true;
|
|
29
|
+
/**
|
|
30
|
+
* *GitHub provider only.* Whether to allow update to pre-release versions. Defaults to `true` if application version contains prerelease components (e.g. `0.12.1-alpha.1`, here `alpha` is a prerelease component), otherwise `false`.
|
|
31
|
+
*
|
|
32
|
+
* If `true`, downgrade will be allowed (`allowDowngrade` will be set to `true`).
|
|
33
|
+
*/
|
|
34
|
+
this.allowPrerelease = false;
|
|
35
|
+
/**
|
|
36
|
+
* *GitHub provider only.* Get all release notes (from current version to latest), not just the latest.
|
|
37
|
+
* @default false
|
|
38
|
+
*/
|
|
39
|
+
this.fullChangelog = false;
|
|
40
|
+
/**
|
|
41
|
+
* Whether to allow version downgrade (when a user from the beta channel wants to go back to the stable channel).
|
|
42
|
+
*
|
|
43
|
+
* Taken in account only if channel differs (pre-release version component in terms of semantic versioning).
|
|
44
|
+
*
|
|
45
|
+
* @default false
|
|
46
|
+
*/
|
|
47
|
+
this.allowDowngrade = false;
|
|
48
|
+
this._channel = null;
|
|
49
|
+
this.downloadedUpdateHelper = null;
|
|
50
|
+
/**
|
|
51
|
+
* The request headers.
|
|
52
|
+
*/
|
|
53
|
+
this.requestHeaders = null;
|
|
54
|
+
this._logger = console;
|
|
55
|
+
// noinspection JSUnusedGlobalSymbols
|
|
56
|
+
/**
|
|
57
|
+
* For type safety you can use signals, e.g. `autoUpdater.signals.updateDownloaded(() => {})` instead of `autoUpdater.on('update-available', () => {})`
|
|
58
|
+
*/
|
|
59
|
+
this.signals = new main_1.UpdaterSignal(this);
|
|
60
|
+
this._appUpdateConfigPath = null;
|
|
61
|
+
this.clientPromise = null;
|
|
62
|
+
this.stagingUserIdPromise = new lazy_val_1.Lazy(() => this.getOrCreateStagingUserId());
|
|
63
|
+
// public, allow to read old config for anyone
|
|
64
|
+
/** @internal */
|
|
65
|
+
this.configOnDisk = new lazy_val_1.Lazy(() => this.loadUpdateConfig());
|
|
66
|
+
this.checkForUpdatesPromise = null;
|
|
67
|
+
this.updateInfoAndProvider = null;
|
|
68
|
+
/**
|
|
69
|
+
* @private
|
|
70
|
+
* @internal
|
|
71
|
+
*/
|
|
72
|
+
this._testOnlyOptions = null;
|
|
73
|
+
this.on("error", (error) => {
|
|
74
|
+
this._logger.error(`Error: ${error.stack || error.message}`);
|
|
75
|
+
});
|
|
76
|
+
if (app == null) {
|
|
77
|
+
this.app = new ElectronAppAdapter_1.ElectronAppAdapter();
|
|
78
|
+
this.httpExecutor = new electronHttpExecutor_1.ElectronHttpExecutor((authInfo, callback) => this.emit("login", authInfo, callback));
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
this.app = app;
|
|
82
|
+
this.httpExecutor = null;
|
|
83
|
+
}
|
|
84
|
+
const currentVersionString = this.app.version;
|
|
85
|
+
const currentVersion = semver_1.parse(currentVersionString);
|
|
86
|
+
if (currentVersion == null) {
|
|
87
|
+
throw builder_util_runtime_1.newError(`App version is not a valid semver version: "${currentVersionString}"`, "ERR_UPDATER_INVALID_VERSION");
|
|
88
|
+
}
|
|
89
|
+
this.currentVersion = currentVersion;
|
|
90
|
+
this.allowPrerelease = hasPrereleaseComponents(currentVersion);
|
|
91
|
+
if (options != null) {
|
|
92
|
+
this.setFeedURL(options);
|
|
93
|
+
if (typeof options !== "string" && options.requestHeaders) {
|
|
94
|
+
this.requestHeaders = options.requestHeaders;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
162
98
|
/**
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
* Applicable only on Windows and Linux.
|
|
99
|
+
* Get the update channel. Not applicable for GitHub. Doesn't return `channel` from the update configuration, only if was previously set.
|
|
166
100
|
*/
|
|
167
|
-
|
|
168
|
-
|
|
101
|
+
get channel() {
|
|
102
|
+
return this._channel;
|
|
103
|
+
}
|
|
169
104
|
/**
|
|
170
|
-
*
|
|
105
|
+
* Set the update channel. Not applicable for GitHub. Overrides `channel` in the update configuration.
|
|
171
106
|
*
|
|
172
|
-
*
|
|
107
|
+
* `allowDowngrade` will be automatically set to `true`. If this behavior is not suitable for you, simple set `allowDowngrade` explicitly after.
|
|
173
108
|
*/
|
|
174
|
-
|
|
175
|
-
|
|
109
|
+
set channel(value) {
|
|
110
|
+
if (this._channel != null) {
|
|
111
|
+
// noinspection SuspiciousTypeOfGuard
|
|
112
|
+
if (typeof value !== "string") {
|
|
113
|
+
throw builder_util_runtime_1.newError(`Channel must be a string, but got: ${value}`, "ERR_UPDATER_INVALID_CHANNEL");
|
|
114
|
+
}
|
|
115
|
+
else if (value.length === 0) {
|
|
116
|
+
throw builder_util_runtime_1.newError(`Channel must be not an empty string`, "ERR_UPDATER_INVALID_CHANNEL");
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
this._channel = value;
|
|
120
|
+
this.allowDowngrade = true;
|
|
121
|
+
}
|
|
122
|
+
// noinspection JSMethodCanBeStatic,JSUnusedGlobalSymbols
|
|
123
|
+
get netSession() {
|
|
124
|
+
return electronHttpExecutor_1.getNetSession();
|
|
125
|
+
}
|
|
176
126
|
/**
|
|
177
|
-
*
|
|
178
|
-
*
|
|
127
|
+
* The logger. You can pass [electron-log](https://github.com/megahertz/electron-log), [winston](https://github.com/winstonjs/winston) or another logger with the following interface: `{ info(), warn(), error() }`.
|
|
128
|
+
* Set it to `null` if you would like to disable a logging feature.
|
|
179
129
|
*/
|
|
180
|
-
|
|
181
|
-
|
|
130
|
+
get logger() {
|
|
131
|
+
return this._logger;
|
|
132
|
+
}
|
|
133
|
+
set logger(value) {
|
|
134
|
+
this._logger = value == null ? new NoOpLogger() : value;
|
|
135
|
+
}
|
|
136
|
+
// noinspection JSUnusedGlobalSymbols
|
|
182
137
|
/**
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
* Taken in account only if channel differs (pre-release version component in terms of semantic versioning).
|
|
186
|
-
*
|
|
187
|
-
* @default false
|
|
138
|
+
* test only
|
|
139
|
+
* @private
|
|
188
140
|
*/
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
141
|
+
set updateConfigPath(value) {
|
|
142
|
+
this.clientPromise = null;
|
|
143
|
+
this._appUpdateConfigPath = value;
|
|
144
|
+
this.configOnDisk = new lazy_val_1.Lazy(() => this.loadUpdateConfig());
|
|
145
|
+
}
|
|
146
|
+
//noinspection JSMethodCanBeStatic,JSUnusedGlobalSymbols
|
|
147
|
+
getFeedURL() {
|
|
148
|
+
return "Deprecated. Do not use it.";
|
|
149
|
+
}
|
|
193
150
|
/**
|
|
194
|
-
*
|
|
151
|
+
* Configure update provider. If value is `string`, [GenericServerOptions](/configuration/publish#genericserveroptions) will be set with value as `url`.
|
|
152
|
+
* @param options If you want to override configuration in the `app-update.yml`.
|
|
195
153
|
*/
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
154
|
+
setFeedURL(options) {
|
|
155
|
+
const runtimeOptions = this.createProviderRuntimeOptions();
|
|
156
|
+
// https://github.com/electron-userland/electron-builder/issues/1105
|
|
157
|
+
let provider;
|
|
158
|
+
if (typeof options === "string") {
|
|
159
|
+
provider = new GenericProvider_1.GenericProvider({ provider: "generic", url: options }, this, {
|
|
160
|
+
...runtimeOptions,
|
|
161
|
+
isUseMultipleRangeRequest: providerFactory_1.isUrlProbablySupportMultiRangeRequests(options),
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
provider = providerFactory_1.createClient(options, this, runtimeOptions);
|
|
166
|
+
}
|
|
167
|
+
this.clientPromise = Promise.resolve(provider);
|
|
168
|
+
}
|
|
200
169
|
/**
|
|
201
|
-
*
|
|
170
|
+
* Asks the server whether there is an update.
|
|
202
171
|
*/
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
172
|
+
checkForUpdates() {
|
|
173
|
+
let checkForUpdatesPromise = this.checkForUpdatesPromise;
|
|
174
|
+
if (checkForUpdatesPromise != null) {
|
|
175
|
+
this._logger.info("Checking for update (already in progress)");
|
|
176
|
+
return checkForUpdatesPromise;
|
|
177
|
+
}
|
|
178
|
+
const nullizePromise = () => (this.checkForUpdatesPromise = null);
|
|
179
|
+
this._logger.info("Checking for update");
|
|
180
|
+
checkForUpdatesPromise = this.doCheckForUpdates()
|
|
181
|
+
.then(it => {
|
|
182
|
+
nullizePromise();
|
|
183
|
+
return it;
|
|
184
|
+
})
|
|
185
|
+
.catch(e => {
|
|
186
|
+
nullizePromise();
|
|
187
|
+
this.emit("error", e, `Cannot check for updates: ${(e.stack || e).toString()}`);
|
|
188
|
+
throw e;
|
|
189
|
+
});
|
|
190
|
+
this.checkForUpdatesPromise = checkForUpdatesPromise;
|
|
191
|
+
return checkForUpdatesPromise;
|
|
192
|
+
}
|
|
193
|
+
isUpdaterActive() {
|
|
194
|
+
if (!this.app.isPackaged) {
|
|
195
|
+
this._logger.info("Skip checkForUpdatesAndNotify because application is not packed");
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
return true;
|
|
199
|
+
}
|
|
200
|
+
// noinspection JSUnusedGlobalSymbols
|
|
201
|
+
checkForUpdatesAndNotify(downloadNotification) {
|
|
202
|
+
if (!this.isUpdaterActive()) {
|
|
203
|
+
return Promise.resolve(null);
|
|
204
|
+
}
|
|
205
|
+
return this.checkForUpdates().then(it => {
|
|
206
|
+
const downloadPromise = it.downloadPromise;
|
|
207
|
+
if (downloadPromise == null) {
|
|
208
|
+
if (this._logger.debug != null) {
|
|
209
|
+
this._logger.debug("checkForUpdatesAndNotify called, downloadPromise is null");
|
|
210
|
+
}
|
|
211
|
+
return it;
|
|
212
|
+
}
|
|
213
|
+
void downloadPromise.then(() => {
|
|
214
|
+
const notificationContent = AppUpdater.formatDownloadNotification(it.updateInfo.version, this.app.name, downloadNotification);
|
|
215
|
+
new (require("electron").Notification)(notificationContent).show();
|
|
216
|
+
});
|
|
217
|
+
return it;
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
static formatDownloadNotification(version, appName, downloadNotification) {
|
|
221
|
+
if (downloadNotification == null) {
|
|
222
|
+
downloadNotification = {
|
|
223
|
+
title: "A new update is ready to install",
|
|
224
|
+
body: `{appName} version {version} has been downloaded and will be automatically installed on exit`,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
downloadNotification = {
|
|
228
|
+
title: downloadNotification.title.replace("{appName}", appName).replace("{version}", version),
|
|
229
|
+
body: downloadNotification.body.replace("{appName}", appName).replace("{version}", version),
|
|
230
|
+
};
|
|
231
|
+
return downloadNotification;
|
|
232
|
+
}
|
|
233
|
+
async isStagingMatch(updateInfo) {
|
|
234
|
+
const rawStagingPercentage = updateInfo.stagingPercentage;
|
|
235
|
+
let stagingPercentage = rawStagingPercentage;
|
|
236
|
+
if (stagingPercentage == null) {
|
|
237
|
+
return true;
|
|
238
|
+
}
|
|
239
|
+
stagingPercentage = parseInt(stagingPercentage, 10);
|
|
240
|
+
if (isNaN(stagingPercentage)) {
|
|
241
|
+
this._logger.warn(`Staging percentage is NaN: ${rawStagingPercentage}`);
|
|
242
|
+
return true;
|
|
243
|
+
}
|
|
244
|
+
// convert from user 0-100 to internal 0-1
|
|
245
|
+
stagingPercentage = stagingPercentage / 100;
|
|
246
|
+
const stagingUserId = await this.stagingUserIdPromise.value;
|
|
247
|
+
const val = builder_util_runtime_1.UUID.parse(stagingUserId).readUInt32BE(12);
|
|
248
|
+
const percentage = val / 0xffffffff;
|
|
249
|
+
this._logger.info(`Staging percentage: ${stagingPercentage}, percentage: ${percentage}, user id: ${stagingUserId}`);
|
|
250
|
+
return percentage < stagingPercentage;
|
|
251
|
+
}
|
|
252
|
+
computeFinalHeaders(headers) {
|
|
253
|
+
if (this.requestHeaders != null) {
|
|
254
|
+
Object.assign(headers, this.requestHeaders);
|
|
255
|
+
}
|
|
256
|
+
return headers;
|
|
257
|
+
}
|
|
258
|
+
async isUpdateAvailable(updateInfo) {
|
|
259
|
+
const latestVersion = semver_1.parse(updateInfo.version);
|
|
260
|
+
if (latestVersion == null) {
|
|
261
|
+
throw builder_util_runtime_1.newError(`This file could not be downloaded, or the latest version (from update server) does not have a valid semver version: "${updateInfo.version}"`, "ERR_UPDATER_INVALID_VERSION");
|
|
262
|
+
}
|
|
263
|
+
const currentVersion = this.currentVersion;
|
|
264
|
+
if (semver_1.eq(latestVersion, currentVersion)) {
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
const isStagingMatch = await this.isStagingMatch(updateInfo);
|
|
268
|
+
if (!isStagingMatch) {
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
// https://github.com/electron-userland/electron-builder/pull/3111#issuecomment-405033227
|
|
272
|
+
// https://github.com/electron-userland/electron-builder/pull/3111#issuecomment-405030797
|
|
273
|
+
const isLatestVersionNewer = semver_1.gt(latestVersion, currentVersion);
|
|
274
|
+
const isLatestVersionOlder = semver_1.lt(latestVersion, currentVersion);
|
|
275
|
+
if (isLatestVersionNewer) {
|
|
276
|
+
return true;
|
|
277
|
+
}
|
|
278
|
+
return this.allowDowngrade && isLatestVersionOlder;
|
|
279
|
+
}
|
|
280
|
+
async getUpdateInfoAndProvider() {
|
|
281
|
+
await this.app.whenReady();
|
|
282
|
+
if (this.clientPromise == null) {
|
|
283
|
+
this.clientPromise = this.configOnDisk.value.then(it => providerFactory_1.createClient(it, this, this.createProviderRuntimeOptions()));
|
|
284
|
+
}
|
|
285
|
+
const client = await this.clientPromise;
|
|
286
|
+
const stagingUserId = await this.stagingUserIdPromise.value;
|
|
287
|
+
client.setRequestHeaders(this.computeFinalHeaders({ "x-user-staging-id": stagingUserId }));
|
|
288
|
+
return {
|
|
289
|
+
info: await client.getLatestVersion(),
|
|
290
|
+
provider: client,
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
|
294
|
+
createProviderRuntimeOptions() {
|
|
295
|
+
return {
|
|
296
|
+
isUseMultipleRangeRequest: true,
|
|
297
|
+
platform: this._testOnlyOptions == null ? process.platform : this._testOnlyOptions.platform,
|
|
298
|
+
executor: this.httpExecutor,
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
async doCheckForUpdates() {
|
|
302
|
+
this.emit("checking-for-update");
|
|
303
|
+
const result = await this.getUpdateInfoAndProvider();
|
|
304
|
+
const updateInfo = result.info;
|
|
305
|
+
if (!(await this.isUpdateAvailable(updateInfo))) {
|
|
306
|
+
this._logger.info(`Update for version ${this.currentVersion} is not available (latest version: ${updateInfo.version}, downgrade is ${this.allowDowngrade ? "allowed" : "disallowed"}).`);
|
|
307
|
+
this.emit("update-not-available", updateInfo);
|
|
308
|
+
return {
|
|
309
|
+
versionInfo: updateInfo,
|
|
310
|
+
updateInfo,
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
this.updateInfoAndProvider = result;
|
|
314
|
+
this.onUpdateAvailable(updateInfo);
|
|
315
|
+
const cancellationToken = new builder_util_runtime_1.CancellationToken();
|
|
316
|
+
//noinspection ES6MissingAwait
|
|
317
|
+
return {
|
|
318
|
+
versionInfo: updateInfo,
|
|
319
|
+
updateInfo,
|
|
320
|
+
cancellationToken,
|
|
321
|
+
downloadPromise: this.autoDownload ? this.downloadUpdate(cancellationToken) : null,
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
onUpdateAvailable(updateInfo) {
|
|
325
|
+
this._logger.info(`Found version ${updateInfo.version} (url: ${builder_util_runtime_1.asArray(updateInfo.files)
|
|
326
|
+
.map(it => it.url)
|
|
327
|
+
.join(", ")})`);
|
|
328
|
+
this.emit("update-available", updateInfo);
|
|
329
|
+
}
|
|
214
330
|
/**
|
|
215
|
-
*
|
|
216
|
-
* @
|
|
331
|
+
* Start downloading update manually. You can use this method if `autoDownload` option is set to `false`.
|
|
332
|
+
* @returns {Promise<string>} Path to downloaded file.
|
|
217
333
|
*/
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
/**
|
|
298
|
-
* test only
|
|
299
|
-
* @private
|
|
300
|
-
*/
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
set updateConfigPath(value) {
|
|
304
|
-
this.clientPromise = null;
|
|
305
|
-
this._appUpdateConfigPath = value;
|
|
306
|
-
this.configOnDisk = new (_lazyVal().Lazy)(() => this.loadUpdateConfig());
|
|
307
|
-
} //noinspection JSMethodCanBeStatic,JSUnusedGlobalSymbols
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
getFeedURL() {
|
|
311
|
-
return "Deprecated. Do not use it.";
|
|
312
|
-
}
|
|
313
|
-
/**
|
|
314
|
-
* Configure update provider. If value is `string`, [GenericServerOptions](/configuration/publish#genericserveroptions) will be set with value as `url`.
|
|
315
|
-
* @param options If you want to override configuration in the `app-update.yml`.
|
|
316
|
-
*/
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
setFeedURL(options) {
|
|
320
|
-
const runtimeOptions = this.createProviderRuntimeOptions(); // https://github.com/electron-userland/electron-builder/issues/1105
|
|
321
|
-
|
|
322
|
-
let provider;
|
|
323
|
-
|
|
324
|
-
if (typeof options === "string") {
|
|
325
|
-
provider = new (_GenericProvider().GenericProvider)({
|
|
326
|
-
provider: "generic",
|
|
327
|
-
url: options
|
|
328
|
-
}, this, { ...runtimeOptions,
|
|
329
|
-
isUseMultipleRangeRequest: (0, _providerFactory().isUrlProbablySupportMultiRangeRequests)(options)
|
|
330
|
-
});
|
|
331
|
-
} else {
|
|
332
|
-
provider = (0, _providerFactory().createClient)(options, this, runtimeOptions);
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
this.clientPromise = Promise.resolve(provider);
|
|
336
|
-
}
|
|
337
|
-
/**
|
|
338
|
-
* Asks the server whether there is an update.
|
|
339
|
-
*/
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
checkForUpdates() {
|
|
343
|
-
let checkForUpdatesPromise = this.checkForUpdatesPromise;
|
|
344
|
-
|
|
345
|
-
if (checkForUpdatesPromise != null) {
|
|
346
|
-
this._logger.info("Checking for update (already in progress)");
|
|
347
|
-
|
|
348
|
-
return checkForUpdatesPromise;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
const nullizePromise = () => this.checkForUpdatesPromise = null;
|
|
352
|
-
|
|
353
|
-
this._logger.info("Checking for update");
|
|
354
|
-
|
|
355
|
-
checkForUpdatesPromise = this.doCheckForUpdates().then(it => {
|
|
356
|
-
nullizePromise();
|
|
357
|
-
return it;
|
|
358
|
-
}).catch(e => {
|
|
359
|
-
nullizePromise();
|
|
360
|
-
this.emit("error", e, `Cannot check for updates: ${(e.stack || e).toString()}`);
|
|
361
|
-
throw e;
|
|
362
|
-
});
|
|
363
|
-
this.checkForUpdatesPromise = checkForUpdatesPromise;
|
|
364
|
-
return checkForUpdatesPromise;
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
isUpdaterActive() {
|
|
368
|
-
if (!this.app.isPackaged) {
|
|
369
|
-
this._logger.info("Skip checkForUpdatesAndNotify because application is not packed");
|
|
370
|
-
|
|
371
|
-
return false;
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
return true;
|
|
375
|
-
} // noinspection JSUnusedGlobalSymbols
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
checkForUpdatesAndNotify(downloadNotification) {
|
|
379
|
-
if (!this.isUpdaterActive()) {
|
|
380
|
-
return Promise.resolve(null);
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
return this.checkForUpdates().then(it => {
|
|
384
|
-
const downloadPromise = it.downloadPromise;
|
|
385
|
-
|
|
386
|
-
if (downloadPromise == null) {
|
|
387
|
-
const debug = this._logger.debug;
|
|
388
|
-
|
|
389
|
-
if (debug != null) {
|
|
390
|
-
debug("checkForUpdatesAndNotify called, downloadPromise is null");
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
return it;
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
downloadPromise.then(() => {
|
|
397
|
-
const notificationContent = this.formatDownloadNotification(it.updateInfo.version, this.app.name, downloadNotification);
|
|
398
|
-
new (_electron().Notification)(notificationContent).show();
|
|
399
|
-
});
|
|
400
|
-
return it;
|
|
401
|
-
});
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
formatDownloadNotification(version, appName, downloadNotification) {
|
|
405
|
-
if (downloadNotification == null) {
|
|
406
|
-
downloadNotification = {
|
|
407
|
-
title: "A new update is ready to install",
|
|
408
|
-
body: `{appName} version {version} has been downloaded and will be automatically installed on exit`
|
|
409
|
-
};
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
downloadNotification = {
|
|
413
|
-
title: downloadNotification.title.replace("{appName}", appName).replace("{version}", version),
|
|
414
|
-
body: downloadNotification.body.replace("{appName}", appName).replace("{version}", version)
|
|
415
|
-
};
|
|
416
|
-
return downloadNotification;
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
async isStagingMatch(updateInfo) {
|
|
420
|
-
const rawStagingPercentage = updateInfo.stagingPercentage;
|
|
421
|
-
let stagingPercentage = rawStagingPercentage;
|
|
422
|
-
|
|
423
|
-
if (stagingPercentage == null) {
|
|
424
|
-
return true;
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
stagingPercentage = parseInt(stagingPercentage, 10);
|
|
428
|
-
|
|
429
|
-
if (isNaN(stagingPercentage)) {
|
|
430
|
-
this._logger.warn(`Staging percentage is NaN: ${rawStagingPercentage}`);
|
|
431
|
-
|
|
432
|
-
return true;
|
|
433
|
-
} // convert from user 0-100 to internal 0-1
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
stagingPercentage = stagingPercentage / 100;
|
|
437
|
-
const stagingUserId = await this.stagingUserIdPromise.value;
|
|
438
|
-
|
|
439
|
-
const val = _builderUtilRuntime().UUID.parse(stagingUserId).readUInt32BE(12);
|
|
440
|
-
|
|
441
|
-
const percentage = val / 0xFFFFFFFF;
|
|
442
|
-
|
|
443
|
-
this._logger.info(`Staging percentage: ${stagingPercentage}, percentage: ${percentage}, user id: ${stagingUserId}`);
|
|
444
|
-
|
|
445
|
-
return percentage < stagingPercentage;
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
computeFinalHeaders(headers) {
|
|
449
|
-
if (this.requestHeaders != null) {
|
|
450
|
-
Object.assign(headers, this.requestHeaders);
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
return headers;
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
async isUpdateAvailable(updateInfo) {
|
|
457
|
-
const latestVersion = (0, _semver().parse)(updateInfo.version);
|
|
458
|
-
|
|
459
|
-
if (latestVersion == null) {
|
|
460
|
-
throw (0, _builderUtilRuntime().newError)(`This file could not be downloaded, or the latest version (from update server) does not have a valid semver version: "${updateInfo.version}"`, "ERR_UPDATER_INVALID_VERSION");
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
const currentVersion = this.currentVersion;
|
|
464
|
-
|
|
465
|
-
if ((0, _semver().eq)(latestVersion, currentVersion)) {
|
|
466
|
-
return false;
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
const isStagingMatch = await this.isStagingMatch(updateInfo);
|
|
470
|
-
|
|
471
|
-
if (!isStagingMatch) {
|
|
472
|
-
return false;
|
|
473
|
-
} // https://github.com/electron-userland/electron-builder/pull/3111#issuecomment-405033227
|
|
474
|
-
// https://github.com/electron-userland/electron-builder/pull/3111#issuecomment-405030797
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
const isLatestVersionNewer = (0, _semver().gt)(latestVersion, currentVersion);
|
|
478
|
-
const isLatestVersionOlder = (0, _semver().lt)(latestVersion, currentVersion);
|
|
479
|
-
|
|
480
|
-
if (isLatestVersionNewer) {
|
|
481
|
-
return true;
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
return this.allowDowngrade && isLatestVersionOlder;
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
async getUpdateInfoAndProvider() {
|
|
488
|
-
await this.app.whenReady();
|
|
489
|
-
|
|
490
|
-
if (this.clientPromise == null) {
|
|
491
|
-
this.clientPromise = this.configOnDisk.value.then(it => (0, _providerFactory().createClient)(it, this, this.createProviderRuntimeOptions()));
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
const client = await this.clientPromise;
|
|
495
|
-
const stagingUserId = await this.stagingUserIdPromise.value;
|
|
496
|
-
client.setRequestHeaders(this.computeFinalHeaders({
|
|
497
|
-
"x-user-staging-id": stagingUserId
|
|
498
|
-
}));
|
|
499
|
-
return {
|
|
500
|
-
info: await client.getLatestVersion(),
|
|
501
|
-
provider: client
|
|
502
|
-
};
|
|
503
|
-
} // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
createProviderRuntimeOptions() {
|
|
507
|
-
return {
|
|
508
|
-
isUseMultipleRangeRequest: true,
|
|
509
|
-
platform: this._testOnlyOptions == null ? process.platform : this._testOnlyOptions.platform,
|
|
510
|
-
executor: this.httpExecutor
|
|
511
|
-
};
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
async doCheckForUpdates() {
|
|
515
|
-
this.emit("checking-for-update");
|
|
516
|
-
const result = await this.getUpdateInfoAndProvider();
|
|
517
|
-
const updateInfo = result.info;
|
|
518
|
-
|
|
519
|
-
if (!(await this.isUpdateAvailable(updateInfo))) {
|
|
520
|
-
this._logger.info(`Update for version ${this.currentVersion} is not available (latest version: ${updateInfo.version}, downgrade is ${this.allowDowngrade ? "allowed" : "disallowed"}).`);
|
|
521
|
-
|
|
522
|
-
this.emit("update-not-available", updateInfo);
|
|
523
|
-
return {
|
|
524
|
-
versionInfo: updateInfo,
|
|
525
|
-
updateInfo
|
|
526
|
-
};
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
this.updateInfoAndProvider = result;
|
|
530
|
-
this.onUpdateAvailable(updateInfo);
|
|
531
|
-
const cancellationToken = new (_builderUtilRuntime().CancellationToken)(); //noinspection ES6MissingAwait
|
|
532
|
-
|
|
533
|
-
return {
|
|
534
|
-
versionInfo: updateInfo,
|
|
535
|
-
updateInfo,
|
|
536
|
-
cancellationToken,
|
|
537
|
-
downloadPromise: this.autoDownload ? this.downloadUpdate(cancellationToken) : null
|
|
538
|
-
};
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
onUpdateAvailable(updateInfo) {
|
|
542
|
-
this._logger.info(`Found version ${updateInfo.version} (url: ${(0, _builderUtilRuntime().asArray)(updateInfo.files).map(it => it.url).join(", ")})`);
|
|
543
|
-
|
|
544
|
-
this.emit("update-available", updateInfo);
|
|
545
|
-
}
|
|
546
|
-
/**
|
|
547
|
-
* Start downloading update manually. You can use this method if `autoDownload` option is set to `false`.
|
|
548
|
-
* @returns {Promise<string>} Path to downloaded file.
|
|
549
|
-
*/
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
downloadUpdate(cancellationToken = new (_builderUtilRuntime().CancellationToken)()) {
|
|
553
|
-
const updateInfoAndProvider = this.updateInfoAndProvider;
|
|
554
|
-
|
|
555
|
-
if (updateInfoAndProvider == null) {
|
|
556
|
-
const error = new Error("Please check update first");
|
|
557
|
-
this.dispatchError(error);
|
|
558
|
-
return Promise.reject(error);
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
this._logger.info(`Downloading update from ${(0, _builderUtilRuntime().asArray)(updateInfoAndProvider.info.files).map(it => it.url).join(", ")}`);
|
|
562
|
-
|
|
563
|
-
const errorHandler = e => {
|
|
564
|
-
// https://github.com/electron-userland/electron-builder/issues/1150#issuecomment-436891159
|
|
565
|
-
if (!(e instanceof _builderUtilRuntime().CancellationError)) {
|
|
334
|
+
downloadUpdate(cancellationToken = new builder_util_runtime_1.CancellationToken()) {
|
|
335
|
+
const updateInfoAndProvider = this.updateInfoAndProvider;
|
|
336
|
+
if (updateInfoAndProvider == null) {
|
|
337
|
+
const error = new Error("Please check update first");
|
|
338
|
+
this.dispatchError(error);
|
|
339
|
+
return Promise.reject(error);
|
|
340
|
+
}
|
|
341
|
+
this._logger.info(`Downloading update from ${builder_util_runtime_1.asArray(updateInfoAndProvider.info.files)
|
|
342
|
+
.map(it => it.url)
|
|
343
|
+
.join(", ")}`);
|
|
344
|
+
const errorHandler = (e) => {
|
|
345
|
+
// https://github.com/electron-userland/electron-builder/issues/1150#issuecomment-436891159
|
|
346
|
+
if (!(e instanceof builder_util_runtime_1.CancellationError)) {
|
|
347
|
+
try {
|
|
348
|
+
this.dispatchError(e);
|
|
349
|
+
}
|
|
350
|
+
catch (nestedError) {
|
|
351
|
+
this._logger.warn(`Cannot dispatch error event: ${nestedError.stack || nestedError}`);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
return e;
|
|
355
|
+
};
|
|
356
|
+
try {
|
|
357
|
+
return this.doDownloadUpdate({
|
|
358
|
+
updateInfoAndProvider,
|
|
359
|
+
requestHeaders: this.computeRequestHeaders(updateInfoAndProvider.provider),
|
|
360
|
+
cancellationToken,
|
|
361
|
+
}).catch(e => {
|
|
362
|
+
throw errorHandler(e);
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
catch (e) {
|
|
366
|
+
return Promise.reject(errorHandler(e));
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
dispatchError(e) {
|
|
370
|
+
this.emit("error", e, (e.stack || e).toString());
|
|
371
|
+
}
|
|
372
|
+
dispatchUpdateDownloaded(event) {
|
|
373
|
+
this.emit(main_1.UPDATE_DOWNLOADED, event);
|
|
374
|
+
}
|
|
375
|
+
async loadUpdateConfig() {
|
|
376
|
+
if (this._appUpdateConfigPath == null) {
|
|
377
|
+
this._appUpdateConfigPath = this.app.appUpdateConfigPath;
|
|
378
|
+
}
|
|
379
|
+
return js_yaml_1.load(await fs_extra_1.readFile(this._appUpdateConfigPath, "utf-8"));
|
|
380
|
+
}
|
|
381
|
+
computeRequestHeaders(provider) {
|
|
382
|
+
const fileExtraDownloadHeaders = provider.fileExtraDownloadHeaders;
|
|
383
|
+
if (fileExtraDownloadHeaders != null) {
|
|
384
|
+
const requestHeaders = this.requestHeaders;
|
|
385
|
+
return requestHeaders == null
|
|
386
|
+
? fileExtraDownloadHeaders
|
|
387
|
+
: {
|
|
388
|
+
...fileExtraDownloadHeaders,
|
|
389
|
+
...requestHeaders,
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
return this.computeFinalHeaders({ accept: "*/*" });
|
|
393
|
+
}
|
|
394
|
+
async getOrCreateStagingUserId() {
|
|
395
|
+
const file = path.join(this.app.userDataPath, ".updaterId");
|
|
396
|
+
try {
|
|
397
|
+
const id = await fs_extra_1.readFile(file, "utf-8");
|
|
398
|
+
if (builder_util_runtime_1.UUID.check(id)) {
|
|
399
|
+
return id;
|
|
400
|
+
}
|
|
401
|
+
else {
|
|
402
|
+
this._logger.warn(`Staging user id file exists, but content was invalid: ${id}`);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
catch (e) {
|
|
406
|
+
if (e.code !== "ENOENT") {
|
|
407
|
+
this._logger.warn(`Couldn't read staging user ID, creating a blank one: ${e}`);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
const id = builder_util_runtime_1.UUID.v5(crypto_1.randomBytes(4096), builder_util_runtime_1.UUID.OID);
|
|
411
|
+
this._logger.info(`Generated new staging user ID: ${id}`);
|
|
566
412
|
try {
|
|
567
|
-
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
return e;
|
|
574
|
-
};
|
|
575
|
-
|
|
576
|
-
try {
|
|
577
|
-
return this.doDownloadUpdate({
|
|
578
|
-
updateInfoAndProvider,
|
|
579
|
-
requestHeaders: this.computeRequestHeaders(updateInfoAndProvider.provider),
|
|
580
|
-
cancellationToken
|
|
581
|
-
}).catch(e => {
|
|
582
|
-
throw errorHandler(e);
|
|
583
|
-
});
|
|
584
|
-
} catch (e) {
|
|
585
|
-
return Promise.reject(errorHandler(e));
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
dispatchError(e) {
|
|
590
|
-
this.emit("error", e, (e.stack || e).toString());
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
dispatchUpdateDownloaded(event) {
|
|
594
|
-
this.emit(_main().UPDATE_DOWNLOADED, event);
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
async loadUpdateConfig() {
|
|
598
|
-
if (this._appUpdateConfigPath == null) {
|
|
599
|
-
this._appUpdateConfigPath = this.app.appUpdateConfigPath;
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
return (0, _jsYaml().safeLoad)((await (0, _fsExtra().readFile)(this._appUpdateConfigPath, "utf-8")));
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
computeRequestHeaders(provider) {
|
|
606
|
-
const fileExtraDownloadHeaders = provider.fileExtraDownloadHeaders;
|
|
607
|
-
|
|
608
|
-
if (fileExtraDownloadHeaders != null) {
|
|
609
|
-
const requestHeaders = this.requestHeaders;
|
|
610
|
-
return requestHeaders == null ? fileExtraDownloadHeaders : { ...fileExtraDownloadHeaders,
|
|
611
|
-
...requestHeaders
|
|
612
|
-
};
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
return this.computeFinalHeaders({
|
|
616
|
-
accept: "*/*"
|
|
617
|
-
});
|
|
618
|
-
}
|
|
619
|
-
|
|
620
|
-
async getOrCreateStagingUserId() {
|
|
621
|
-
const file = path.join(this.app.userDataPath, ".updaterId");
|
|
622
|
-
|
|
623
|
-
try {
|
|
624
|
-
const id = await (0, _fsExtra().readFile)(file, "utf-8");
|
|
625
|
-
|
|
626
|
-
if (_builderUtilRuntime().UUID.check(id)) {
|
|
413
|
+
await fs_extra_1.outputFile(file, id);
|
|
414
|
+
}
|
|
415
|
+
catch (e) {
|
|
416
|
+
this._logger.warn(`Couldn't write out staging user ID: ${e}`);
|
|
417
|
+
}
|
|
627
418
|
return id;
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
const done = async isSaveCache => {
|
|
731
|
-
await downloadedUpdateHelper.setDownloadedFile(updateFile, packageFile, updateInfo, fileInfo, updateFileName, isSaveCache);
|
|
732
|
-
await taskOptions.done({ ...updateInfo,
|
|
733
|
-
downloadedFile: updateFile
|
|
734
|
-
});
|
|
735
|
-
return packageFile == null ? [updateFile] : [updateFile, packageFile];
|
|
736
|
-
};
|
|
737
|
-
|
|
738
|
-
const log = this._logger;
|
|
739
|
-
const cachedUpdateFile = await downloadedUpdateHelper.validateDownloadedPath(updateFile, updateInfo, fileInfo, log);
|
|
740
|
-
|
|
741
|
-
if (cachedUpdateFile != null) {
|
|
742
|
-
updateFile = cachedUpdateFile;
|
|
743
|
-
return await done(false);
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
const removeFileIfAny = async () => {
|
|
747
|
-
await downloadedUpdateHelper.clear().catch(() => {// ignore
|
|
748
|
-
});
|
|
749
|
-
return await (0, _fsExtra().unlink)(updateFile).catch(() => {// ignore
|
|
750
|
-
});
|
|
751
|
-
};
|
|
752
|
-
|
|
753
|
-
const tempUpdateFile = await (0, _DownloadedUpdateHelper().createTempUpdateFile)(`temp-${updateFileName}`, cacheDir, log);
|
|
754
|
-
|
|
755
|
-
try {
|
|
756
|
-
await taskOptions.task(tempUpdateFile, downloadOptions, packageFile, removeFileIfAny);
|
|
757
|
-
await (0, _fsExtra().rename)(tempUpdateFile, updateFile);
|
|
758
|
-
} catch (e) {
|
|
759
|
-
await removeFileIfAny();
|
|
760
|
-
|
|
761
|
-
if (e instanceof _builderUtilRuntime().CancellationError) {
|
|
762
|
-
log.info("cancelled");
|
|
763
|
-
this.emit("update-cancelled", updateInfo);
|
|
764
|
-
}
|
|
765
|
-
|
|
766
|
-
throw e;
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
log.info(`New version ${version} has been downloaded to ${updateFile}`);
|
|
770
|
-
return await done(true);
|
|
771
|
-
}
|
|
772
|
-
|
|
419
|
+
}
|
|
420
|
+
/** @internal */
|
|
421
|
+
get isAddNoCacheQuery() {
|
|
422
|
+
const headers = this.requestHeaders;
|
|
423
|
+
// https://github.com/electron-userland/electron-builder/issues/3021
|
|
424
|
+
if (headers == null) {
|
|
425
|
+
return true;
|
|
426
|
+
}
|
|
427
|
+
for (const headerName of Object.keys(headers)) {
|
|
428
|
+
const s = headerName.toLowerCase();
|
|
429
|
+
if (s === "authorization" || s === "private-token") {
|
|
430
|
+
return false;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
return true;
|
|
434
|
+
}
|
|
435
|
+
async getOrCreateDownloadHelper() {
|
|
436
|
+
let result = this.downloadedUpdateHelper;
|
|
437
|
+
if (result == null) {
|
|
438
|
+
const dirName = (await this.configOnDisk.value).updaterCacheDirName;
|
|
439
|
+
const logger = this._logger;
|
|
440
|
+
if (dirName == null) {
|
|
441
|
+
logger.error("updaterCacheDirName is not specified in app-update.yml Was app build using at least electron-builder 20.34.0?");
|
|
442
|
+
}
|
|
443
|
+
const cacheDir = path.join(this.app.baseCachePath, dirName || this.app.name);
|
|
444
|
+
if (logger.debug != null) {
|
|
445
|
+
logger.debug(`updater cache dir: ${cacheDir}`);
|
|
446
|
+
}
|
|
447
|
+
result = new DownloadedUpdateHelper_1.DownloadedUpdateHelper(cacheDir);
|
|
448
|
+
this.downloadedUpdateHelper = result;
|
|
449
|
+
}
|
|
450
|
+
return result;
|
|
451
|
+
}
|
|
452
|
+
async executeDownload(taskOptions) {
|
|
453
|
+
const fileInfo = taskOptions.fileInfo;
|
|
454
|
+
const downloadOptions = {
|
|
455
|
+
headers: taskOptions.downloadUpdateOptions.requestHeaders,
|
|
456
|
+
cancellationToken: taskOptions.downloadUpdateOptions.cancellationToken,
|
|
457
|
+
sha2: fileInfo.info.sha2,
|
|
458
|
+
sha512: fileInfo.info.sha512,
|
|
459
|
+
};
|
|
460
|
+
if (this.listenerCount(main_1.DOWNLOAD_PROGRESS) > 0) {
|
|
461
|
+
downloadOptions.onProgress = it => this.emit(main_1.DOWNLOAD_PROGRESS, it);
|
|
462
|
+
}
|
|
463
|
+
const updateInfo = taskOptions.downloadUpdateOptions.updateInfoAndProvider.info;
|
|
464
|
+
const version = updateInfo.version;
|
|
465
|
+
const packageInfo = fileInfo.packageInfo;
|
|
466
|
+
function getCacheUpdateFileName() {
|
|
467
|
+
// NodeJS URL doesn't decode automatically
|
|
468
|
+
const urlPath = decodeURIComponent(taskOptions.fileInfo.url.pathname);
|
|
469
|
+
if (urlPath.endsWith(`.${taskOptions.fileExtension}`)) {
|
|
470
|
+
return path.posix.basename(urlPath);
|
|
471
|
+
}
|
|
472
|
+
else {
|
|
473
|
+
// url like /latest, generate name
|
|
474
|
+
return `update.${taskOptions.fileExtension}`;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
const downloadedUpdateHelper = await this.getOrCreateDownloadHelper();
|
|
478
|
+
const cacheDir = downloadedUpdateHelper.cacheDirForPendingUpdate;
|
|
479
|
+
await fs_extra_1.ensureDir(cacheDir);
|
|
480
|
+
const updateFileName = getCacheUpdateFileName();
|
|
481
|
+
let updateFile = path.join(cacheDir, updateFileName);
|
|
482
|
+
const packageFile = packageInfo == null ? null : path.join(cacheDir, `package-${version}${path.extname(packageInfo.path) || ".7z"}`);
|
|
483
|
+
const done = async (isSaveCache) => {
|
|
484
|
+
await downloadedUpdateHelper.setDownloadedFile(updateFile, packageFile, updateInfo, fileInfo, updateFileName, isSaveCache);
|
|
485
|
+
await taskOptions.done({
|
|
486
|
+
...updateInfo,
|
|
487
|
+
downloadedFile: updateFile,
|
|
488
|
+
});
|
|
489
|
+
return packageFile == null ? [updateFile] : [updateFile, packageFile];
|
|
490
|
+
};
|
|
491
|
+
const log = this._logger;
|
|
492
|
+
const cachedUpdateFile = await downloadedUpdateHelper.validateDownloadedPath(updateFile, updateInfo, fileInfo, log);
|
|
493
|
+
if (cachedUpdateFile != null) {
|
|
494
|
+
updateFile = cachedUpdateFile;
|
|
495
|
+
return await done(false);
|
|
496
|
+
}
|
|
497
|
+
const removeFileIfAny = async () => {
|
|
498
|
+
await downloadedUpdateHelper.clear().catch(() => {
|
|
499
|
+
// ignore
|
|
500
|
+
});
|
|
501
|
+
return await fs_extra_1.unlink(updateFile).catch(() => {
|
|
502
|
+
// ignore
|
|
503
|
+
});
|
|
504
|
+
};
|
|
505
|
+
const tempUpdateFile = await DownloadedUpdateHelper_1.createTempUpdateFile(`temp-${updateFileName}`, cacheDir, log);
|
|
506
|
+
try {
|
|
507
|
+
await taskOptions.task(tempUpdateFile, downloadOptions, packageFile, removeFileIfAny);
|
|
508
|
+
await fs_extra_1.rename(tempUpdateFile, updateFile);
|
|
509
|
+
}
|
|
510
|
+
catch (e) {
|
|
511
|
+
await removeFileIfAny();
|
|
512
|
+
if (e instanceof builder_util_runtime_1.CancellationError) {
|
|
513
|
+
log.info("cancelled");
|
|
514
|
+
this.emit("update-cancelled", updateInfo);
|
|
515
|
+
}
|
|
516
|
+
throw e;
|
|
517
|
+
}
|
|
518
|
+
log.info(`New version ${version} has been downloaded to ${updateFile}`);
|
|
519
|
+
return await done(true);
|
|
520
|
+
}
|
|
773
521
|
}
|
|
774
|
-
|
|
775
522
|
exports.AppUpdater = AppUpdater;
|
|
776
|
-
|
|
777
523
|
function hasPrereleaseComponents(version) {
|
|
778
|
-
|
|
779
|
-
|
|
524
|
+
const versionPrereleaseComponent = semver_1.prerelease(version);
|
|
525
|
+
return versionPrereleaseComponent != null && versionPrereleaseComponent.length > 0;
|
|
780
526
|
}
|
|
781
527
|
/** @private */
|
|
782
|
-
|
|
783
|
-
|
|
784
528
|
class NoOpLogger {
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
}
|
|
798
|
-
|
|
529
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
530
|
+
info(message) {
|
|
531
|
+
// ignore
|
|
532
|
+
}
|
|
533
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
534
|
+
warn(message) {
|
|
535
|
+
// ignore
|
|
536
|
+
}
|
|
537
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
538
|
+
error(message) {
|
|
539
|
+
// ignore
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
exports.NoOpLogger = NoOpLogger;
|
|
799
543
|
//# sourceMappingURL=AppUpdater.js.map
|