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.
Files changed (70) hide show
  1. package/LICENSE +22 -0
  2. package/out/AppAdapter.js +19 -28
  3. package/out/AppAdapter.js.map +1 -1
  4. package/out/AppImageUpdater.js +103 -173
  5. package/out/AppImageUpdater.js.map +1 -1
  6. package/out/AppUpdater.d.ts +1 -3
  7. package/out/AppUpdater.js +517 -773
  8. package/out/AppUpdater.js.map +1 -1
  9. package/out/BaseUpdater.js +79 -103
  10. package/out/BaseUpdater.js.map +1 -1
  11. package/out/DownloadedUpdateHelper.js +150 -224
  12. package/out/DownloadedUpdateHelper.js.map +1 -1
  13. package/out/ElectronAppAdapter.js +35 -63
  14. package/out/ElectronAppAdapter.js.map +1 -1
  15. package/out/MacUpdater.d.ts +1 -1
  16. package/out/MacUpdater.js +132 -182
  17. package/out/MacUpdater.js.map +1 -1
  18. package/out/NoOpLogger.d.ts +6 -0
  19. package/out/NoOpLogger.js +19 -0
  20. package/out/NoOpLogger.js.map +1 -0
  21. package/out/NsisUpdater.js +199 -331
  22. package/out/NsisUpdater.js.map +1 -1
  23. package/out/differentialDownloader/DataSplitter.js +180 -252
  24. package/out/differentialDownloader/DataSplitter.js.map +1 -1
  25. package/out/differentialDownloader/DifferentialDownloader.d.ts +3 -0
  26. package/out/differentialDownloader/DifferentialDownloader.js +243 -308
  27. package/out/differentialDownloader/DifferentialDownloader.js.map +1 -1
  28. package/out/differentialDownloader/FileWithEmbeddedBlockMapDifferentialDownloader.js +29 -65
  29. package/out/differentialDownloader/FileWithEmbeddedBlockMapDifferentialDownloader.js.map +1 -1
  30. package/out/differentialDownloader/GenericDifferentialDownloader.js +7 -21
  31. package/out/differentialDownloader/GenericDifferentialDownloader.js.map +1 -1
  32. package/out/differentialDownloader/ProgressDifferentialDownloadCallbackTransform.d.ts +32 -0
  33. package/out/differentialDownloader/ProgressDifferentialDownloadCallbackTransform.js +90 -0
  34. package/out/differentialDownloader/ProgressDifferentialDownloadCallbackTransform.js.map +1 -0
  35. package/out/differentialDownloader/downloadPlanBuilder.js +99 -124
  36. package/out/differentialDownloader/downloadPlanBuilder.js.map +1 -1
  37. package/out/differentialDownloader/multipleRangeDownloader.js +99 -148
  38. package/out/differentialDownloader/multipleRangeDownloader.js.map +1 -1
  39. package/out/electronHttpExecutor.js +73 -106
  40. package/out/electronHttpExecutor.js.map +1 -1
  41. package/out/event.d.ts +35 -0
  42. package/out/event.js +39 -0
  43. package/out/event.js.map +1 -0
  44. package/out/log.d.ts +11 -0
  45. package/out/log.js +19 -0
  46. package/out/log.js.map +1 -0
  47. package/out/main.d.ts +1 -4
  48. package/out/main.js +60 -212
  49. package/out/main.js.map +1 -1
  50. package/out/providerFactory.js +49 -105
  51. package/out/providerFactory.js.map +1 -1
  52. package/out/providers/BintrayProvider.d.ts +2 -2
  53. package/out/providers/BintrayProvider.js +40 -95
  54. package/out/providers/BintrayProvider.js.map +1 -1
  55. package/out/providers/GenericProvider.d.ts +2 -2
  56. package/out/providers/GenericProvider.js +46 -80
  57. package/out/providers/GenericProvider.js.map +1 -1
  58. package/out/providers/GitHubProvider.d.ts +2 -2
  59. package/out/providers/GitHubProvider.js +122 -201
  60. package/out/providers/GitHubProvider.js.map +1 -1
  61. package/out/providers/PrivateGitHubProvider.js +87 -165
  62. package/out/providers/PrivateGitHubProvider.js.map +1 -1
  63. package/out/providers/Provider.js +122 -173
  64. package/out/providers/Provider.js.map +1 -1
  65. package/out/util.d.ts +5 -0
  66. package/out/util.js +42 -0
  67. package/out/util.js.map +1 -0
  68. package/out/windowsExecutableCodeSignatureVerifier.js +99 -139
  69. package/out/windowsExecutableCodeSignatureVerifier.js.map +1 -1
  70. 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
- function _builderUtilRuntime() {
9
- const data = require("builder-util-runtime");
10
-
11
- _builderUtilRuntime = function () {
12
- return data;
13
- };
14
-
15
- return data;
16
- }
17
-
18
- function _crypto() {
19
- const data = require("crypto");
20
-
21
- _crypto = function () {
22
- return data;
23
- };
24
-
25
- return data;
26
- }
27
-
28
- function _electron() {
29
- const data = require("electron");
30
-
31
- _electron = function () {
32
- return data;
33
- };
34
-
35
- return data;
36
- }
37
-
38
- function _events() {
39
- const data = require("events");
40
-
41
- _events = function () {
42
- return data;
43
- };
44
-
45
- return data;
46
- }
47
-
48
- function _fsExtra() {
49
- const data = require("fs-extra");
50
-
51
- _fsExtra = function () {
52
- return data;
53
- };
54
-
55
- return data;
56
- }
57
-
58
- function _jsYaml() {
59
- const data = require("js-yaml");
60
-
61
- _jsYaml = function () {
62
- return data;
63
- };
64
-
65
- return data;
66
- }
67
-
68
- function _lazyVal() {
69
- const data = require("lazy-val");
70
-
71
- _lazyVal = function () {
72
- return data;
73
- };
74
-
75
- return data;
76
- }
77
-
78
- var path = _interopRequireWildcard(require("path"));
79
-
80
- function _semver() {
81
- const data = require("semver");
82
-
83
- _semver = function () {
84
- return data;
85
- };
86
-
87
- return data;
88
- }
89
-
90
- function _DownloadedUpdateHelper() {
91
- const data = require("./DownloadedUpdateHelper");
92
-
93
- _DownloadedUpdateHelper = function () {
94
- return data;
95
- };
96
-
97
- return data;
98
- }
99
-
100
- function _ElectronAppAdapter() {
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
- * Whether to automatically install a downloaded update on app quit (if `quitAndInstall` was not called before).
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
- this.autoInstallOnAppQuit = true;
101
+ get channel() {
102
+ return this._channel;
103
+ }
169
104
  /**
170
- * *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`.
105
+ * Set the update channel. Not applicable for GitHub. Overrides `channel` in the update configuration.
171
106
  *
172
- * If `true`, downgrade will be allowed (`allowDowngrade` will be set to `true`).
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
- this.allowPrerelease = false;
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
- * *GitHub provider only.* Get all release notes (from current version to latest), not just the latest.
178
- * @default false
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
- this.fullChangelog = false;
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
- * Whether to allow version downgrade (when a user from the beta channel wants to go back to the stable channel).
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
- this.allowDowngrade = false;
191
- this._channel = null;
192
- this.downloadedUpdateHelper = null;
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
- * The request headers.
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
- this.requestHeaders = null;
198
- this._logger = console; // noinspection JSUnusedGlobalSymbols
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
- * For type safety you can use signals, e.g. `autoUpdater.signals.updateDownloaded(() => {})` instead of `autoUpdater.on('update-available', () => {})`
170
+ * Asks the server whether there is an update.
202
171
  */
203
-
204
- this.signals = new (_main().UpdaterSignal)(this);
205
- this._appUpdateConfigPath = null;
206
- this.clientPromise = null;
207
- this.stagingUserIdPromise = new (_lazyVal().Lazy)(() => this.getOrCreateStagingUserId()); // public, allow to read old config for anyone
208
-
209
- /** @internal */
210
-
211
- this.configOnDisk = new (_lazyVal().Lazy)(() => this.loadUpdateConfig());
212
- this.checkForUpdatesPromise = null;
213
- this.updateInfoAndProvider = null;
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
- * @private
216
- * @internal
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
- this._testOnlyOptions = null;
220
- this.on("error", error => {
221
- this._logger.error(`Error: ${error.stack || error.message}`);
222
- });
223
-
224
- if (app == null) {
225
- this.app = new (_ElectronAppAdapter().ElectronAppAdapter)();
226
- this.httpExecutor = new (_electronHttpExecutor().ElectronHttpExecutor)((authInfo, callback) => this.emit("login", authInfo, callback));
227
- } else {
228
- this.app = app;
229
- this.httpExecutor = null;
230
- }
231
-
232
- const currentVersionString = this.app.version;
233
- const currentVersion = (0, _semver().parse)(currentVersionString);
234
-
235
- if (currentVersion == null) {
236
- throw (0, _builderUtilRuntime().newError)(`App version is not a valid semver version: "${currentVersionString}"`, "ERR_UPDATER_INVALID_VERSION");
237
- }
238
-
239
- this.currentVersion = currentVersion;
240
- this.allowPrerelease = hasPrereleaseComponents(currentVersion);
241
-
242
- if (options != null) {
243
- this.setFeedURL(options);
244
-
245
- if (typeof options !== "string" && options.requestHeaders) {
246
- this.requestHeaders = options.requestHeaders;
247
- }
248
- }
249
- }
250
- /**
251
- * Get the update channel. Not applicable for GitHub. Doesn't return `channel` from the update configuration, only if was previously set.
252
- */
253
-
254
-
255
- get channel() {
256
- return this._channel;
257
- }
258
- /**
259
- * Set the update channel. Not applicable for GitHub. Overrides `channel` in the update configuration.
260
- *
261
- * `allowDowngrade` will be automatically set to `true`. If this behavior is not suitable for you, simple set `allowDowngrade` explicitly after.
262
- */
263
-
264
-
265
- set channel(value) {
266
- if (this._channel != null) {
267
- // noinspection SuspiciousTypeOfGuard
268
- if (typeof value !== "string") {
269
- throw (0, _builderUtilRuntime().newError)(`Channel must be a string, but got: ${value}`, "ERR_UPDATER_INVALID_CHANNEL");
270
- } else if (value.length === 0) {
271
- throw (0, _builderUtilRuntime().newError)(`Channel must be not an empty string`, "ERR_UPDATER_INVALID_CHANNEL");
272
- }
273
- }
274
-
275
- this._channel = value;
276
- this.allowDowngrade = true;
277
- } // noinspection JSMethodCanBeStatic,JSUnusedGlobalSymbols
278
-
279
-
280
- get netSession() {
281
- return (0, _electronHttpExecutor().getNetSession)();
282
- }
283
- /**
284
- * 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() }`.
285
- * Set it to `null` if you would like to disable a logging feature.
286
- */
287
-
288
-
289
- get logger() {
290
- return this._logger;
291
- }
292
-
293
- set logger(value) {
294
- this._logger = value == null ? new NoOpLogger() : value;
295
- } // noinspection JSUnusedGlobalSymbols
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
- this.dispatchError(e);
568
- } catch (nestedError) {
569
- this._logger.warn(`Cannot dispatch error event: ${nestedError.stack || nestedError}`);
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
- } else {
629
- this._logger.warn(`Staging user id file exists, but content was invalid: ${id}`);
630
- }
631
- } catch (e) {
632
- if (e.code !== "ENOENT") {
633
- this._logger.warn(`Couldn't read staging user ID, creating a blank one: ${e}`);
634
- }
635
- }
636
-
637
- const id = _builderUtilRuntime().UUID.v5((0, _crypto().randomBytes)(4096), _builderUtilRuntime().UUID.OID);
638
-
639
- this._logger.info(`Generated new staging user ID: ${id}`);
640
-
641
- try {
642
- await (0, _fsExtra().outputFile)(file, id);
643
- } catch (e) {
644
- this._logger.warn(`Couldn't write out staging user ID: ${e}`);
645
- }
646
-
647
- return id;
648
- }
649
- /** @internal */
650
-
651
-
652
- get isAddNoCacheQuery() {
653
- const headers = this.requestHeaders; // https://github.com/electron-userland/electron-builder/issues/3021
654
-
655
- if (headers == null) {
656
- return true;
657
- }
658
-
659
- for (const headerName of Object.keys(headers)) {
660
- const s = headerName.toLowerCase();
661
-
662
- if (s === "authorization" || s === "private-token") {
663
- return false;
664
- }
665
- }
666
-
667
- return true;
668
- }
669
-
670
- async getOrCreateDownloadHelper() {
671
- let result = this.downloadedUpdateHelper;
672
-
673
- if (result == null) {
674
- const dirName = (await this.configOnDisk.value).updaterCacheDirName;
675
- const logger = this._logger;
676
-
677
- if (dirName == null) {
678
- logger.error("updaterCacheDirName is not specified in app-update.yml Was app build using at least electron-builder 20.34.0?");
679
- }
680
-
681
- const cacheDir = path.join(this.app.baseCachePath, dirName || this.app.name);
682
-
683
- if (logger.debug != null) {
684
- logger.debug(`updater cache dir: ${cacheDir}`);
685
- }
686
-
687
- result = new (_DownloadedUpdateHelper().DownloadedUpdateHelper)(cacheDir);
688
- this.downloadedUpdateHelper = result;
689
- }
690
-
691
- return result;
692
- }
693
-
694
- async executeDownload(taskOptions) {
695
- const fileInfo = taskOptions.fileInfo;
696
- const downloadOptions = {
697
- headers: taskOptions.downloadUpdateOptions.requestHeaders,
698
- cancellationToken: taskOptions.downloadUpdateOptions.cancellationToken,
699
- sha2: fileInfo.info.sha2,
700
- sha512: fileInfo.info.sha512
701
- };
702
-
703
- if (this.listenerCount(_main().DOWNLOAD_PROGRESS) > 0) {
704
- downloadOptions.onProgress = it => this.emit(_main().DOWNLOAD_PROGRESS, it);
705
- }
706
-
707
- const updateInfo = taskOptions.downloadUpdateOptions.updateInfoAndProvider.info;
708
- const version = updateInfo.version;
709
- const packageInfo = fileInfo.packageInfo;
710
-
711
- function getCacheUpdateFileName() {
712
- // NodeJS URL doesn't decode automatically
713
- const urlPath = decodeURIComponent(taskOptions.fileInfo.url.pathname);
714
-
715
- if (urlPath.endsWith(`.${taskOptions.fileExtension}`)) {
716
- return path.posix.basename(urlPath);
717
- } else {
718
- // url like /latest, generate name
719
- return `update.${taskOptions.fileExtension}`;
720
- }
721
- }
722
-
723
- const downloadedUpdateHelper = await this.getOrCreateDownloadHelper();
724
- const cacheDir = downloadedUpdateHelper.cacheDirForPendingUpdate;
725
- await (0, _fsExtra().ensureDir)(cacheDir);
726
- const updateFileName = getCacheUpdateFileName();
727
- let updateFile = path.join(cacheDir, updateFileName);
728
- const packageFile = packageInfo == null ? null : path.join(cacheDir, `package-${version}${path.extname(packageInfo.path) || ".7z"}`);
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
- const versionPrereleaseComponent = (0, _semver().prerelease)(version);
779
- return versionPrereleaseComponent != null && versionPrereleaseComponent.length > 0;
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
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
786
- info(message) {} // ignore
787
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
788
-
789
-
790
- warn(message) {} // ignore
791
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
792
-
793
-
794
- error(message) {// ignore
795
- }
796
-
797
- } exports.NoOpLogger = NoOpLogger;
798
- // __ts-babel@6.0.4
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