| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633 |
- "use strict";
- Object.defineProperty(exports, "__esModule", {
- value: true
- });
- exports.NoOpLogger = exports.AppUpdater = void 0;
- function _bluebirdLst() {
- const data = require("bluebird-lst");
- _bluebirdLst = function () {
- return data;
- };
- return data;
- }
- function _builderUtilRuntime() {
- const data = require("builder-util-runtime");
- _builderUtilRuntime = function () {
- return data;
- };
- return data;
- }
- function _crypto() {
- const data = require("crypto");
- _crypto = function () {
- return data;
- };
- return data;
- }
- function _electron() {
- const data = require("electron");
- _electron = function () {
- return data;
- };
- return data;
- }
- function _electronIsDev() {
- const data = _interopRequireDefault(require("electron-is-dev"));
- _electronIsDev = function () {
- return data;
- };
- return data;
- }
- function _events() {
- const data = require("events");
- _events = function () {
- return data;
- };
- return data;
- }
- function _fsExtraP() {
- const data = require("fs-extra-p");
- _fsExtraP = function () {
- return data;
- };
- return data;
- }
- function _jsYaml() {
- const data = require("js-yaml");
- _jsYaml = function () {
- return data;
- };
- return data;
- }
- function _lazyVal() {
- const data = require("lazy-val");
- _lazyVal = function () {
- return data;
- };
- return data;
- }
- var path = _interopRequireWildcard(require("path"));
- function _semver() {
- const data = require("semver");
- _semver = function () {
- return data;
- };
- return data;
- }
- require("source-map-support/register");
- function _electronHttpExecutor() {
- const data = require("./electronHttpExecutor");
- _electronHttpExecutor = function () {
- return data;
- };
- return data;
- }
- function _GenericProvider() {
- const data = require("./GenericProvider");
- _GenericProvider = function () {
- return data;
- };
- return data;
- }
- function _main() {
- const data = require("./main");
- _main = function () {
- return data;
- };
- return data;
- }
- function _providerFactory() {
- const data = require("./providerFactory");
- _providerFactory = function () {
- return data;
- };
- return data;
- }
- function _DownloadedUpdateHelper() {
- const data = require("./DownloadedUpdateHelper");
- _DownloadedUpdateHelper = function () {
- return data;
- };
- return data;
- }
- function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
- class AppUpdater extends _events().EventEmitter {
- constructor(options, app) {
- super();
- /**
- * Whether to automatically download an update when it is found.
- */
- this.autoDownload = true;
- /**
- * Whether to automatically install a downloaded update on app quit (if `quitAndInstall` was not called before).
- *
- * Applicable only on Windows and Linux.
- */
- this.autoInstallOnAppQuit = true;
- /**
- * *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`.
- *
- * If `true`, downgrade will be allowed (`allowDowngrade` will be set to `true`).
- */
- this.allowPrerelease = false;
- /**
- * *GitHub provider only.* Get all release notes (from current version to latest), not just the latest.
- * @default false
- */
- this.fullChangelog = false;
- /**
- * Whether to allow version downgrade (when a user from the beta channel wants to go back to the stable channel).
- * @default false
- */
- this.allowDowngrade = false;
- this._channel = null;
- /**
- * The request headers.
- */
- this.requestHeaders = null;
- this._logger = console;
- /**
- * For type safety you can use signals, e.g. `autoUpdater.signals.updateDownloaded(() => {})` instead of `autoUpdater.on('update-available', () => {})`
- */
- this.signals = new (_main().UpdaterSignal)(this);
- this._appUpdateConfigPath = null;
- this.updateAvailable = false;
- this.clientPromise = null;
- this.stagingUserIdPromise = new (_lazyVal().Lazy)(() => this.getOrCreateStagingUserId()); // public, allow to read old config for anyone
- this.configOnDisk = new (_lazyVal().Lazy)(() => this.loadUpdateConfig());
- this.checkForUpdatesPromise = null;
- this.updateInfo = null;
- this.on("error", error => {
- this._logger.error(`Error: ${error.stack || error.message}`);
- });
- if (app != null || global.__test_app != null) {
- this.app = app || global.__test_app;
- this.untilAppReady = Promise.resolve();
- this.httpExecutor = null;
- } else {
- this.app = require("electron").app;
- this.httpExecutor = new (_electronHttpExecutor().ElectronHttpExecutor)((authInfo, callback) => this.emit("login", authInfo, callback));
- this.untilAppReady = new Promise(resolve => {
- if (this.app.isReady()) {
- resolve();
- } else {
- this.app.on("ready", resolve);
- }
- });
- }
- this.downloadedUpdateHelper = new (_DownloadedUpdateHelper().DownloadedUpdateHelper)(this.app.getPath("userData"));
- const currentVersionString = this.app.getVersion();
- const currentVersion = (0, _semver().valid)(currentVersionString);
- if (currentVersion == null) {
- throw (0, _builderUtilRuntime().newError)(`App version is not a valid semver version: "${currentVersionString}`, "ERR_UPDATER_INVALID_VERSION");
- }
- this.currentVersion = currentVersion;
- this.allowPrerelease = hasPrereleaseComponents(this.currentVersion);
- if (options != null) {
- this.setFeedURL(options);
- }
- }
- /**
- * Get the update channel. Not applicable for GitHub. Doesn't return `channel` from the update configuration, only if was previously set.
- */
- get channel() {
- return this._channel;
- }
- /**
- * Set the update channel. Not applicable for GitHub. Overrides `channel` in the update configuration.
- *
- * `allowDowngrade` will be automatically set to `true`. If this behavior is not suitable for you, simple set `allowDowngrade` explicitly after.
- */
- set channel(value) {
- if (this._channel != null) {
- if (typeof value !== "string") {
- throw (0, _builderUtilRuntime().newError)(`Channel must be a string, but got: ${value}`, "ERR_UPDATER_INVALID_CHANNEL");
- } else if (value.length === 0) {
- throw (0, _builderUtilRuntime().newError)(`Channel must be not an empty string`, "ERR_UPDATER_INVALID_CHANNEL");
- }
- }
- this._channel = value;
- this.allowDowngrade = true;
- }
- /**
- * 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() }`.
- * Set it to `null` if you would like to disable a logging feature.
- */
- get logger() {
- return this._logger;
- }
- set logger(value) {
- this._logger = value == null ? new NoOpLogger() : value;
- } // noinspection JSUnusedGlobalSymbols
- /**
- * test only
- * @private
- */
- set updateConfigPath(value) {
- this.clientPromise = null;
- this._appUpdateConfigPath = value;
- this.configOnDisk = new (_lazyVal().Lazy)(() => this.loadUpdateConfig());
- }
- get provider() {
- return this.clientPromise;
- } //noinspection JSMethodCanBeStatic,JSUnusedGlobalSymbols
- getFeedURL() {
- return "Deprecated. Do not use it.";
- }
- /**
- * Configure update provider. If value is `string`, [GenericServerOptions](/configuration/publish.md#genericserveroptions) will be set with value as `url`.
- * @param options If you want to override configuration in the `app-update.yml`.
- */
- setFeedURL(options) {
- // https://github.com/electron-userland/electron-builder/issues/1105
- let provider;
- if (typeof options === "string") {
- provider = new (_GenericProvider().GenericProvider)({
- provider: "generic",
- url: options
- }, this);
- } else {
- provider = (0, _providerFactory().createClient)(options, this);
- }
- this.clientPromise = Promise.resolve(provider);
- }
- /**
- * Asks the server whether there is an update.
- */
- checkForUpdates() {
- let checkForUpdatesPromise = this.checkForUpdatesPromise;
- if (checkForUpdatesPromise != null) {
- return checkForUpdatesPromise;
- }
- checkForUpdatesPromise = this._checkForUpdates();
- this.checkForUpdatesPromise = checkForUpdatesPromise;
- const nullizePromise = () => this.checkForUpdatesPromise = null;
- checkForUpdatesPromise.then(nullizePromise).catch(nullizePromise);
- return checkForUpdatesPromise;
- }
- checkForUpdatesAndNotify() {
- if (_electronIsDev().default) {
- return Promise.resolve(null);
- }
- const checkForUpdatesPromise = this.checkForUpdates();
- checkForUpdatesPromise.then(it => {
- const downloadPromise = it.downloadPromise;
- if (downloadPromise == null) {
- this._logger.warn("checkForUpdatesAndNotify called, but downloadPromise is null");
- return;
- }
- downloadPromise.then(() => {
- new (_electron().Notification)({
- title: "A new update is ready to install",
- body: `${this.app.getName()} version ${it.updateInfo.version} is downloaded and will be automatically installed on exit`
- }).show();
- });
- });
- return checkForUpdatesPromise;
- }
- isStagingMatch(updateInfo) {
- var _this = this;
- return (0, _bluebirdLst().coroutine)(function* () {
- const rawStagingPercentage = updateInfo.stagingPercentage;
- let stagingPercentage = rawStagingPercentage;
- if (stagingPercentage == null) {
- return true;
- }
- stagingPercentage = parseInt(stagingPercentage, 10);
- if (isNaN(stagingPercentage)) {
- _this._logger.warn(`Staging percentage is NaN: ${rawStagingPercentage}`);
- return true;
- } // convert from user 0-100 to internal 0-1
- stagingPercentage = stagingPercentage / 100;
- const stagingUserId = yield _this.stagingUserIdPromise.value;
- const val = _builderUtilRuntime().UUID.parse(stagingUserId).readUInt32BE(12);
- const percentage = val / 0xFFFFFFFF;
- _this._logger.info(`Staging percentage: ${stagingPercentage}, percentage: ${percentage}, user id: ${stagingUserId}`);
- return percentage < stagingPercentage;
- })();
- }
- _checkForUpdates() {
- var _this2 = this;
- return (0, _bluebirdLst().coroutine)(function* () {
- try {
- yield _this2.untilAppReady;
- _this2._logger.info("Checking for update");
- _this2.emit("checking-for-update");
- return yield _this2.doCheckForUpdates();
- } catch (e) {
- _this2.emit("error", e, `Cannot check for updates: ${(e.stack || e).toString()}`);
- throw e;
- }
- })();
- }
- computeFinalHeaders(headers) {
- if (this.requestHeaders != null) {
- Object.assign(headers, this.requestHeaders);
- }
- return headers;
- }
- getUpdateInfo() {
- var _this3 = this;
- return (0, _bluebirdLst().coroutine)(function* () {
- yield _this3.untilAppReady;
- if (_this3.clientPromise == null) {
- _this3.clientPromise = _this3.configOnDisk.value.then(it => (0, _providerFactory().createClient)(it, _this3));
- }
- const client = yield _this3.clientPromise;
- const stagingUserId = yield _this3.stagingUserIdPromise.value;
- client.setRequestHeaders(_this3.computeFinalHeaders({
- "X-User-Staging-Id": stagingUserId
- }));
- return yield client.getLatestVersion();
- })();
- }
- doCheckForUpdates() {
- var _this4 = this;
- return (0, _bluebirdLst().coroutine)(function* () {
- const updateInfo = yield _this4.getUpdateInfo();
- const latestVersion = (0, _semver().valid)(updateInfo.version);
- if (latestVersion == null) {
- throw (0, _builderUtilRuntime().newError)(`Latest version (from update server) is not valid semver version: "${latestVersion}`, "ERR_UPDATER_INVALID_VERSION");
- }
- const isStagingMatch = yield _this4.isStagingMatch(updateInfo);
- if (!isStagingMatch || (_this4.allowDowngrade && !hasPrereleaseComponents(latestVersion) ? (0, _semver().eq)(latestVersion, _this4.currentVersion) : !(0, _semver().gt)(latestVersion, _this4.currentVersion))) {
- _this4.updateAvailable = false;
- _this4._logger.info(`Update for version ${_this4.currentVersion} is not available (latest version: ${updateInfo.version}, downgrade is ${_this4.allowDowngrade ? "allowed" : "disallowed"}).`);
- _this4.emit("update-not-available", updateInfo);
- return {
- versionInfo: updateInfo,
- updateInfo
- };
- }
- _this4.updateAvailable = true;
- _this4.updateInfo = updateInfo;
- _this4.onUpdateAvailable(updateInfo);
- const cancellationToken = new (_builderUtilRuntime().CancellationToken)(); //noinspection ES6MissingAwait
- return {
- versionInfo: updateInfo,
- updateInfo,
- cancellationToken,
- downloadPromise: _this4.autoDownload ? _this4.downloadUpdate(cancellationToken) : null
- };
- })();
- }
- onUpdateAvailable(updateInfo) {
- this._logger.info(`Found version ${updateInfo.version} (url: ${(0, _builderUtilRuntime().asArray)(updateInfo.files).map(it => it.url).join(", ")})`);
- this.emit("update-available", updateInfo);
- }
- /**
- * Start downloading update manually. You can use this method if `autoDownload` option is set to `false`.
- * @returns {Promise<string>} Path to downloaded file.
- */
- downloadUpdate(cancellationToken = new (_builderUtilRuntime().CancellationToken)()) {
- var _this5 = this;
- return (0, _bluebirdLst().coroutine)(function* () {
- const updateInfo = _this5.updateInfo;
- if (updateInfo == null) {
- const error = new Error("Please check update first");
- _this5.dispatchError(error);
- throw error;
- }
- _this5._logger.info(`Downloading update from ${(0, _builderUtilRuntime().asArray)(updateInfo.files).map(it => it.url).join(", ")}`);
- try {
- return yield _this5.doDownloadUpdate(updateInfo, cancellationToken);
- } catch (e) {
- _this5.dispatchError(e);
- throw e;
- }
- })();
- }
- dispatchError(e) {
- this.emit("error", e, (e.stack || e).toString());
- }
- loadUpdateConfig() {
- var _this6 = this;
- return (0, _bluebirdLst().coroutine)(function* () {
- if (_this6._appUpdateConfigPath == null) {
- _this6._appUpdateConfigPath = _electronIsDev().default ? path.join(_this6.app.getAppPath(), "dev-app-update.yml") : path.join(process.resourcesPath, "app-update.yml");
- }
- return (0, _jsYaml().safeLoad)((yield (0, _fsExtraP().readFile)(_this6._appUpdateConfigPath, "utf-8")));
- })();
- }
- /*** @private */
- computeRequestHeaders() {
- var _this7 = this;
- return (0, _bluebirdLst().coroutine)(function* () {
- const fileExtraDownloadHeaders = (yield _this7.provider).fileExtraDownloadHeaders;
- if (fileExtraDownloadHeaders != null) {
- const requestHeaders = _this7.requestHeaders;
- return requestHeaders == null ? fileExtraDownloadHeaders : Object.assign({}, fileExtraDownloadHeaders, requestHeaders);
- }
- return _this7.computeFinalHeaders({
- Accept: "*/*"
- });
- })();
- }
- getOrCreateStagingUserId() {
- var _this8 = this;
- return (0, _bluebirdLst().coroutine)(function* () {
- const file = path.join(_this8.app.getPath("userData"), ".updaterId");
- try {
- const id = yield (0, _fsExtraP().readFile)(file, "utf-8");
- if (_builderUtilRuntime().UUID.check(id)) {
- return id;
- } else {
- _this8._logger.warn(`Staging user id file exists, but content was invalid: ${id}`);
- }
- } catch (e) {
- if (e.code !== "ENOENT") {
- _this8._logger.warn(`Couldn't read staging user ID, creating a blank one: ${e}`);
- }
- }
- const id = _builderUtilRuntime().UUID.v5((0, _crypto().randomBytes)(4096), _builderUtilRuntime().UUID.OID);
- _this8._logger.info(`Generated new staging user ID: ${id}`);
- try {
- yield (0, _fsExtraP().outputFile)(file, id);
- } catch (e) {
- _this8._logger.warn(`Couldn't write out staging user ID: ${e}`);
- }
- return id;
- })();
- }
- }
- exports.AppUpdater = AppUpdater;
- function hasPrereleaseComponents(version) {
- const versionPrereleaseComponent = (0, _semver().prerelease)(version);
- return versionPrereleaseComponent != null && versionPrereleaseComponent.length > 0;
- }
- /** @private */
- class NoOpLogger {
- info(message) {// ignore
- }
- warn(message) {// ignore
- }
- error(message) {// ignore
- }
- } exports.NoOpLogger = NoOpLogger;
- //# sourceMappingURL=AppUpdater.js.map
|