Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@todesktop/runtime

Package Overview
Dependencies
Maintainers
3
Versions
113
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@todesktop/runtime - npm Package Compare versions

Comparing version 0.2.0 to 0.2.1

303

dist/AutoUpdater.js
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, privateMap, value) {

@@ -72,15 +81,17 @@ if (!privateMap.has(receiver)) {

}
async checkForUpdates({ source = BuiltInSources.programmaticCall, } = {}) {
this._log("info", ".checkForUpdates called");
if (!__classPrivateFieldGet(this, _hasAppFinishedLaunching)) {
const error = new Error("Cannot checkForUpdates before app is ready (see https://www.electronjs.org/docs/api/app#event-ready)");
this._log("error", error);
throw error;
}
if (!__classPrivateFieldGet(this, _isActive)) {
return {
updateInfo: null,
};
}
return await this._check({ source });
checkForUpdates({ source = BuiltInSources.programmaticCall, } = {}) {
return __awaiter(this, void 0, void 0, function* () {
this._log("info", ".checkForUpdates called");
if (!__classPrivateFieldGet(this, _hasAppFinishedLaunching)) {
const error = new Error("Cannot checkForUpdates before app is ready (see https://www.electronjs.org/docs/api/app#event-ready)");
this._log("error", error);
throw error;
}
if (!__classPrivateFieldGet(this, _isActive)) {
return {
updateInfo: null,
};
}
return yield this._check({ source });
});
}

@@ -97,95 +108,97 @@ restartAndInstall() {

}
async _actuallyPerformCheck() {
this._log("debug", "_actuallyPerformCheck called");
let updateInfo;
try {
updateInfo = await __classPrivateFieldGet(this, _updaterAgent).checkAndDownload();
}
catch (e) {
this._log("debug", "Error during check & download; resetting this.hasUpdateReadyToInstall to be safe");
// When there's an error during the download, electron-updater wipes its temp directory
__classPrivateFieldSet(this, _hasUpdateReadyToInstall, false);
throw e;
}
// Reset the collected sources
const previouslyPendingCheckSources = [
...__classPrivateFieldGet(this, _pendingCheckSources),
];
__classPrivateFieldSet(this, _pendingCheckSources, []);
// No update available; exit early
if (!updateInfo) {
this._log("debug", "No update available");
// To be safe
__classPrivateFieldSet(this, _hasUpdateReadyToInstall, false);
return {
_actuallyPerformCheck() {
return __awaiter(this, void 0, void 0, function* () {
this._log("debug", "_actuallyPerformCheck called");
let updateInfo;
try {
updateInfo = yield __classPrivateFieldGet(this, _updaterAgent).checkAndDownload();
}
catch (e) {
this._log("debug", "Error during check & download; resetting this.hasUpdateReadyToInstall to be safe");
// When there's an error during the download, electron-updater wipes its temp directory
__classPrivateFieldSet(this, _hasUpdateReadyToInstall, false);
throw e;
}
// Reset the collected sources
const previouslyPendingCheckSources = [
...__classPrivateFieldGet(this, _pendingCheckSources),
];
__classPrivateFieldSet(this, _pendingCheckSources, []);
// No update available; exit early
if (!updateInfo) {
this._log("debug", "No update available");
// To be safe
__classPrivateFieldSet(this, _hasUpdateReadyToInstall, false);
return {
updateInfo,
};
}
this._log("debug", "Update available", updateInfo);
__classPrivateFieldSet(this, _hasUpdateReadyToInstall, true);
// Emit the event
const eventPayload = {
sources: previouslyPendingCheckSources,
updateInfo,
};
}
this._log("debug", "Update available", updateInfo);
__classPrivateFieldSet(this, _hasUpdateReadyToInstall, true);
// Emit the event
const eventPayload = {
sources: previouslyPendingCheckSources,
updateInfo,
};
this._log("debug", "Emitting update-downloaded event");
const emitPromise = this.emitAsync("update-downloaded", eventPayload);
/*
If they haven't disabled the default behaviour or they've already been notified of an update
(we don't want to notify them on interval)
*/
if (__classPrivateFieldGet(this, _shouldNotify) && !__classPrivateFieldGet(this, _hasNotified)) {
this._log("debug", "Emitting update-downloaded event");
const emitPromise = this.emitAsync("update-downloaded", eventPayload);
/*
The default behaviour is to notify the end user.
We allow this to be cancelled by returning false from any event listener (plain/Promise),
within a time window. If the time elapses, we carry on with the default behaviour and
ignore the listener response(s).
If they haven't disabled the default behaviour or they've already been notified of an update
(we don't want to notify them on interval)
*/
// This is needed in case they plainly return false and then the setTimeout fires afterwards
let hasReturnedFalseInEventListener = false;
// This will notify the first time it's called. Subsequent calls are ignored
const notify = once(() => {
if (hasReturnedFalseInEventListener) {
return;
}
__classPrivateFieldSet(this, _hasNotified, true);
const notification = new electron.Notification({
title: "A new update is ready to install",
body: `${electron.app.name} version ${updateInfo.version} has been downloaded and will be automatically installed on exit`,
if (__classPrivateFieldGet(this, _shouldNotify) && !__classPrivateFieldGet(this, _hasNotified)) {
/*
The default behaviour is to notify the end user.
We allow this to be cancelled by returning false from any event listener (plain/Promise),
within a time window. If the time elapses, we carry on with the default behaviour and
ignore the listener response(s).
*/
// This is needed in case they plainly return false and then the setTimeout fires afterwards
let hasReturnedFalseInEventListener = false;
// This will notify the first time it's called. Subsequent calls are ignored
const notify = once(() => {
if (hasReturnedFalseInEventListener) {
return;
}
__classPrivateFieldSet(this, _hasNotified, true);
const notification = new electron.Notification({
title: "A new update is ready to install",
body: `${electron.app.name} version ${updateInfo.version} has been downloaded and will be automatically installed on exit`,
});
notification.show();
});
notification.show();
});
// They have a time-limited window to respond. Try to notify when it ends
setTimeout_1.default(() => {
this._log("debug", "before notify call in setTimeout");
notify();
}, 500);
emitPromise
.catch((e) => {
this._log("debug", "event callback errored", e);
// Ignore the error but immediately continue with the default behaviour
notify();
})
.then((responses = []) => {
// Ignore if they have returned false from any listener
if (responses.some((response) => response === false)) {
hasReturnedFalseInEventListener = true;
return;
}
this._log("debug", "calling notify after event listener Promise settled");
// This won't do anything if they took too long to respond
notify();
});
}
else {
// i.e. !shouldNotify
// Reset the collected sources
__classPrivateFieldSet(this, _pendingCheckSources, []);
emitPromise.catch((e) => {
this._log("debug", "event callback errored", e);
// ignore
});
}
// Return as soon as possible (don't wait for listener responses)
return { updateInfo };
// They have a time-limited window to respond. Try to notify when it ends
setTimeout_1.default(() => {
this._log("debug", "before notify call in setTimeout");
notify();
}, 500);
emitPromise
.catch((e) => {
this._log("debug", "event callback errored", e);
// Ignore the error but immediately continue with the default behaviour
notify();
})
.then((responses = []) => {
// Ignore if they have returned false from any listener
if (responses.some((response) => response === false)) {
hasReturnedFalseInEventListener = true;
return;
}
this._log("debug", "calling notify after event listener Promise settled");
// This won't do anything if they took too long to respond
notify();
});
}
else {
// i.e. !shouldNotify
// Reset the collected sources
__classPrivateFieldSet(this, _pendingCheckSources, []);
emitPromise.catch((e) => {
this._log("debug", "event callback errored", e);
// ignore
});
}
// Return as soon as possible (don't wait for listener responses)
return { updateInfo };
});
}

@@ -195,5 +208,5 @@ _autoCheckOnInterval(interval) {

this._log("debug", "checking for update on interval");
setTimeout_1.default(async () => {
setTimeout_1.default(() => __awaiter(this, void 0, void 0, function* () {
try {
await this._check({
yield this._check({
source: BuiltInSources.autoCheckOnInterval,

@@ -208,47 +221,51 @@ });

}
}, interval);
}), interval);
};
checkAfterTimeout();
}
async _autoCheckOnLaunch() {
this._log("debug", "checking for update on launch");
try {
await this._check({
source: BuiltInSources.autoCheckOnLaunch,
_autoCheckOnLaunch() {
return __awaiter(this, void 0, void 0, function* () {
this._log("debug", "checking for update on launch");
try {
yield this._check({
source: BuiltInSources.autoCheckOnLaunch,
});
}
catch (e) {
this._log("error", e);
// Ignore. Auto-check on interval and programmatic API still supported
}
});
}
_check({ source, }) {
return __awaiter(this, void 0, void 0, function* () {
/*
We collect the sources and emit them with the update-downloaded event.
Other noteworthy bits:
- The update check promise is reused by electron-updater.
- We don't want more than one event emitted.
- There's no sorting or de-duplication of the sources, on purpose.
*/
__classPrivateFieldGet(this, _pendingCheckSources).push(source);
this._log("debug", "_check called", {
source,
pendingCheckSources: __classPrivateFieldGet(this, _pendingCheckSources),
});
}
catch (e) {
this._log("error", e);
// Ignore. Auto-check on interval and programmatic API still supported
}
}
async _check({ source, }) {
/*
We collect the sources and emit them with the update-downloaded event.
Other noteworthy bits:
- The update check promise is reused by electron-updater.
- We don't want more than one event emitted.
- There's no sorting or de-duplication of the sources, on purpose.
*/
__classPrivateFieldGet(this, _pendingCheckSources).push(source);
this._log("debug", "_check called", {
source,
pendingCheckSources: __classPrivateFieldGet(this, _pendingCheckSources),
if (__classPrivateFieldGet(this, _pendingUpdateCheckPromise)) {
return __classPrivateFieldGet(this, _pendingUpdateCheckPromise);
}
const onEnd = () => {
__classPrivateFieldSet(this, _pendingUpdateCheckPromise, null);
};
__classPrivateFieldSet(this, _pendingUpdateCheckPromise, this._actuallyPerformCheck()
.then((updateCheckResult) => {
onEnd();
return updateCheckResult;
})
.catch((e) => {
onEnd();
throw e;
}));
return __classPrivateFieldGet(this, _pendingUpdateCheckPromise);
});
if (__classPrivateFieldGet(this, _pendingUpdateCheckPromise)) {
return __classPrivateFieldGet(this, _pendingUpdateCheckPromise);
}
const onEnd = () => {
__classPrivateFieldSet(this, _pendingUpdateCheckPromise, null);
};
__classPrivateFieldSet(this, _pendingUpdateCheckPromise, this._actuallyPerformCheck()
.then((updateCheckResult) => {
onEnd();
return updateCheckResult;
})
.catch((e) => {
onEnd();
throw e;
}));
return __classPrivateFieldGet(this, _pendingUpdateCheckPromise);
}

@@ -255,0 +272,0 @@ /*

@@ -1,1 +0,11 @@

export {};
import AutoUpdater from "./AutoUpdater";
import { LoggerInterface } from "./Logger";
declare class ToDesktop {
autoUpdater: AutoUpdater;
init({ autoUpdater, customLogger, }?: {
autoUpdater?: boolean;
customLogger?: LoggerInterface;
}): void;
}
declare const _default: ToDesktop;
export default _default;

@@ -34,2 +34,3 @@ "use strict";

}
exports.default = todesktop;
module.exports = todesktop;
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, privateMap, value) {

@@ -37,33 +46,35 @@ if (!privateMap.has(receiver)) {

}
async checkAndDownload() {
try {
electronUpdater.autoUpdater.autoDownload = false;
const updateCheckResult = await electronUpdater.autoUpdater.checkForUpdates();
// No update available?
if (!updateCheckResult || !updateCheckResult.updateInfo) {
return null;
checkAndDownload() {
return __awaiter(this, void 0, void 0, function* () {
try {
electronUpdater.autoUpdater.autoDownload = false;
const updateCheckResult = yield electronUpdater.autoUpdater.checkForUpdates();
// No update available?
if (!updateCheckResult || !updateCheckResult.updateInfo) {
return null;
}
// We need to make sure the version is actually newer
const currentVersion = electron.app.getVersion();
const newVersion = updateCheckResult.updateInfo.version;
__classPrivateFieldGet(this, _log).call(this, "debug", "Analysing autoUpdater.checkForUpdates result", {
currentVersion,
newVersion,
updateInfo: updateCheckResult.updateInfo,
});
if (!semver.gt(newVersion, currentVersion)) {
return null;
}
yield electronUpdater.autoUpdater.downloadUpdate(updateCheckResult.cancellationToken);
return {
releaseDate: updateCheckResult.updateInfo.releaseDate,
version: updateCheckResult.updateInfo.version,
};
}
// We need to make sure the version is actually newer
const currentVersion = electron.app.getVersion();
const newVersion = updateCheckResult.updateInfo.version;
__classPrivateFieldGet(this, _log).call(this, "debug", "Analysing autoUpdater.checkForUpdates result", {
currentVersion,
newVersion,
updateInfo: updateCheckResult.updateInfo,
});
if (!semver.gt(newVersion, currentVersion)) {
return null;
catch (e) {
if (e.name === "CancellationError") {
throw new Error("Update check cancelled");
}
throw e;
}
await electronUpdater.autoUpdater.downloadUpdate(updateCheckResult.cancellationToken);
return {
releaseDate: updateCheckResult.updateInfo.releaseDate,
version: updateCheckResult.updateInfo.version,
};
}
catch (e) {
if (e.name === "CancellationError") {
throw new Error("Update check cancelled");
}
throw e;
}
});
}

@@ -122,49 +133,51 @@ restartAndInstall() {

*/
async checkAndDownload() {
return new Promise((resolve, reject) => {
const onError = (err) => {
// eslint-disable-next-line @typescript-eslint/no-use-before-define
removeListeners();
reject(err);
};
const onUpdateDownloaded = (event, releaseNotes, releaseName, releaseDate, updateURL) => {
// eslint-disable-next-line @typescript-eslint/no-use-before-define
removeListeners();
/*
If we can't grab the version from the URL, then just return a fake
version that's higher than the current version.
The server will only respond if the update is actually newer, so the
only issue is if the API user decides to show the version in the UI,
it'll be incorrect.
That's not so bad compared to auto-updates failing because the URL
pattern changed and our runtime library broke (nothing the user can
see / control).
*/
const version = this._getVersionFromNupkgUrl(updateURL) ||
semver.inc(electron.app.getVersion(), "patch");
resolve({
releaseDate: releaseDate.toString(),
version,
checkAndDownload() {
return __awaiter(this, void 0, void 0, function* () {
return new Promise((resolve, reject) => {
const onError = (err) => {
// eslint-disable-next-line @typescript-eslint/no-use-before-define
removeListeners();
reject(err);
};
const onUpdateDownloaded = (event, releaseNotes, releaseName, releaseDate, updateURL) => {
// eslint-disable-next-line @typescript-eslint/no-use-before-define
removeListeners();
/*
If we can't grab the version from the URL, then just return a fake
version that's higher than the current version.
The server will only respond if the update is actually newer, so the
only issue is if the API user decides to show the version in the UI,
it'll be incorrect.
That's not so bad compared to auto-updates failing because the URL
pattern changed and our runtime library broke (nothing the user can
see / control).
*/
const version = this._getVersionFromNupkgUrl(updateURL) ||
semver.inc(electron.app.getVersion(), "patch");
resolve({
releaseDate: releaseDate.toString(),
version,
});
};
const onUpdateNotAvailable = () => {
// eslint-disable-next-line @typescript-eslint/no-use-before-define
removeListeners();
resolve(null);
};
const removeListeners = once(() => {
electron.autoUpdater.off("error", onError);
electron.autoUpdater.off("update-downloaded", onUpdateDownloaded);
electron.autoUpdater.off("update-not-available", onUpdateNotAvailable);
});
};
const onUpdateNotAvailable = () => {
// eslint-disable-next-line @typescript-eslint/no-use-before-define
removeListeners();
resolve(null);
};
const removeListeners = once(() => {
electron.autoUpdater.off("error", onError);
electron.autoUpdater.off("update-downloaded", onUpdateDownloaded);
electron.autoUpdater.off("update-not-available", onUpdateNotAvailable);
electron.autoUpdater.once("error", onError);
electron.autoUpdater.once("update-downloaded", onUpdateDownloaded);
electron.autoUpdater.once("update-not-available", onUpdateNotAvailable);
try {
// This auto-downloads (and the version comparison is automatic)
electron.autoUpdater.checkForUpdates();
}
catch (e) {
onError(e);
}
});
electron.autoUpdater.once("error", onError);
electron.autoUpdater.once("update-downloaded", onUpdateDownloaded);
electron.autoUpdater.once("update-not-available", onUpdateNotAvailable);
try {
// This auto-downloads (and the version comparison is automatic)
electron.autoUpdater.checkForUpdates();
}
catch (e) {
onError(e);
}
});

@@ -171,0 +184,0 @@ }

@@ -7,3 +7,3 @@ {

"name": "@todesktop/runtime",
"version": "0.2.0",
"version": "0.2.1",
"license": "MIT",

@@ -17,3 +17,3 @@ "author": "Adam Lynch <contact@adamlynch.com> (http://adamlynch.com/)",

"scripts": {
"build": "tsc --skipLibCheck --declaration -p .",
"build": "tsc",
"clear-test-cache": "ava reset-cache",

@@ -20,0 +20,0 @@ "lint": "tsc --noEmit --skipLibCheck && eslint . --ext .js,.ts,.tsx",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc