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