This commit is contained in:
rafael-aero
2021-09-03 15:28:34 +02:00
14 changed files with 278 additions and 270 deletions

View File

@@ -1,5 +1,5 @@
variables:
PackageVersion: 13.5.1.$(Build.BuildId)
PackageVersion: 14.0.0.$(Build.BuildId)
projectAPI: './ElectronNET.API/ElectronNET.API.csproj'
projectCLI: './ElectronNET.CLI/ElectronNET.CLI.csproj'

View File

@@ -90,34 +90,41 @@ namespace ElectronNET.API
private static SemaphoreSlim _socketSemaphoreEmit = new SemaphoreSlim(1, 1);
private static SemaphoreSlim _socketSemaphoreHandlers = new SemaphoreSlim(1, 1);
private static TaskCompletionSource _waitForBeingConnected = new TaskCompletionSource();
private static Task _waitForConnection => _waitForBeingConnected.Task;
private static TaskCompletionSource<SocketIO> _connectedSocketTask = new TaskCompletionSource<SocketIO>();
private static Task<SocketIO> _waitForConnection
{
get
{
EnsureSocketTaskIsCreated();
return _connectedSocketTask.Task;
}
}
public static bool IsConnected => _waitForConnection is Task task && task.IsCompletedSuccessfully;
public static void Emit(string eventString, params object[] args)
{
//We don't care about waiting for the event to be emitted, so this doesn't need to be async
Task.Run(async () =>
{
await EmitAsync(eventString, args);
});
Task.Run(() => EmitAsync(eventString, args));
}
private static async Task EmitAsync(string eventString, object[] args)
{
await _waitForConnection;
if (App.SocketDebug)
{
Log("Sending event {0}", eventString);
}
var socket = await _waitForConnection;
await _socketSemaphoreEmit.WaitAsync();
try
{
await Socket.EmitAsync(eventString, args);
await socket.EmitAsync(eventString, args);
}
finally
{
@@ -130,30 +137,6 @@ namespace ElectronNET.API
}
}
internal static void Log(string formatString, params object[] args)
{
if (Logger is object)
{
Logger.LogInformation(formatString, args);
}
else
{
Console.WriteLine(formatString, args);
}
}
internal static void LogError(Exception E, string formatString, params object[] args)
{
if (Logger is object)
{
Logger.LogError(E, formatString, args);
}
else
{
Console.WriteLine(formatString, args);
}
}
/// <summary>
/// This method is only used on places where we need to be sure the event was sent on the socket, such as Quit, Exit, Relaunch and QuitAndInstall methods
/// </summary>
@@ -166,18 +149,19 @@ namespace ElectronNET.API
Log("Sending event {0}", eventString);
}
_waitForConnection.Wait();
_socketSemaphoreEmit.Wait();
try
Task.Run(async () =>
{
Socket.EmitAsync(eventString, args).Wait();
}
finally
{
_socketSemaphoreEmit.Release();
}
var socket = await _waitForConnection;
try
{
await _socketSemaphoreEmit.WaitAsync();
await socket.EmitAsync(eventString, args);
}
finally
{
_socketSemaphoreEmit.Release();
}
}).Wait();
if (App.SocketDebug)
@@ -188,10 +172,12 @@ namespace ElectronNET.API
public static void Off(string eventString)
{
EnsureSocketTaskIsCreated();
_socketSemaphoreHandlers.Wait();
try
{
Socket.Off(eventString);
_socket.Off(eventString);
}
finally
{
@@ -201,10 +187,12 @@ namespace ElectronNET.API
public static void On(string eventString, Action fn)
{
EnsureSocketTaskIsCreated();
_socketSemaphoreHandlers.Wait();
try
{
Socket.On(eventString, _ =>
_socket.On(eventString, _ =>
{
try
{
@@ -224,10 +212,12 @@ namespace ElectronNET.API
public static void On<T>(string eventString, Action<T> fn)
{
EnsureSocketTaskIsCreated();
_socketSemaphoreHandlers.Wait();
try
{
Socket.On(eventString, (o) =>
_socket.On(eventString, (o) =>
{
try
{
@@ -359,101 +349,131 @@ namespace ElectronNET.API
return await taskCompletionSource.Task;
}
private static SocketIO Socket
internal static void Log(string formatString, params object[] args)
{
get
if (Logger is object)
{
if (_socket is null)
Logger.LogInformation(formatString, args);
}
else
{
Console.WriteLine(formatString, args);
}
}
internal static void LogError(Exception E, string formatString, params object[] args)
{
if (Logger is object)
{
Logger.LogError(E, formatString, args);
}
else
{
Console.WriteLine(formatString, args);
Console.WriteLine(E.ToString());
}
}
private static void EnsureSocketTaskIsCreated()
{
if (_socket is null)
{
if (HybridSupport.IsElectronActive)
{
if (HybridSupport.IsElectronActive)
lock (_syncRoot)
{
lock (_syncRoot)
if (_socket is null && HybridSupport.IsElectronActive)
{
if (_socket is null && HybridSupport.IsElectronActive)
var socket = new SocketIO($"http://localhost:{BridgeSettings.SocketPort}", new SocketIOOptions()
{
var socket = new SocketIO($"http://localhost:{BridgeSettings.SocketPort}", new SocketIOOptions()
{
EIO = 3,
Reconnection = true,
ReconnectionAttempts = int.MaxValue,
ReconnectionDelay = 1000,
ReconnectionDelayMax = 5000,
RandomizationFactor = 0.1,
ConnectionTimeout = TimeSpan.FromSeconds(10)
});
EIO = 3,
Reconnection = true,
ReconnectionAttempts = int.MaxValue,
ReconnectionDelay = 1000,
ReconnectionDelayMax = 5000,
RandomizationFactor = 0.5,
ConnectionTimeout = TimeSpan.FromSeconds(10)
});
socket.JsonSerializer = new CamelCaseNewtonsoftJsonSerializer(socket.Options.EIO);
socket.JsonSerializer = new CamelCaseNewtonsoftJsonSerializer(socket.Options.EIO);
socket.OnConnected += (_, __) =>
{
Log("ElectronNET socket connected on port {0}!", BridgeSettings.SocketPort);
_waitForBeingConnected.TrySetResult();
};
socket.OnConnected += (_, __) =>
{
_connectedSocketTask.TrySetResult(socket);
Log("ElectronNET socket connected on port {0}!", BridgeSettings.SocketPort);
};
socket.OnReconnectAttempt += (_, __) =>
{
Log("ElectronNET socket is trying to reconnect on port {0}...", BridgeSettings.SocketPort);
_waitForBeingConnected = new();
};
socket.OnReconnectAttempt += (_, __) =>
{
_connectedSocketTask = new();
Log("ElectronNET socket is trying to reconnect on port {0}...", BridgeSettings.SocketPort);
};
socket.OnReconnectError += (_, ex) =>
{
Log("ElectronNET socket failed to connect {0}", ex);
};
socket.OnReconnectError += (_, ex) =>
{
Log("ElectronNET socket failed to connect {0}", ex);
};
socket.OnReconnected += (_, __) =>
{
Log("ElectronNET socket reconnected on port {0}...", BridgeSettings.SocketPort);
_waitForBeingConnected.TrySetResult();
};
socket.OnReconnected += (_, __) =>
{
_connectedSocketTask.TrySetResult(socket);
Log("ElectronNET socket reconnected on port {0}...", BridgeSettings.SocketPort);
};
socket.OnDisconnected += async (_, reason) =>
{
Log("ElectronNET socket disconnected with reason {0}, trying to reconnect on port {1}!", reason, BridgeSettings.SocketPort);
socket.OnDisconnected += async (_, reason) =>
{
_connectedSocketTask = new();
Log("ElectronNET socket disconnected with reason {0}, trying to reconnect on port {1}!", reason, BridgeSettings.SocketPort);
int i = 0;
_waitForBeingConnected = new();
double miliseconds = 500;
int i = 0;
double miliseconds = 500;
while (true)
while (true)
{
try
{
try
if (!socket.Connected)
{
if (!socket.Connected)
{
await socket.ConnectAsync();
_waitForBeingConnected.TrySetResult(); //Probably was already on the OnConnected call
}
return;
await socket.ConnectAsync();
_connectedSocketTask.TrySetResult(socket); //Probably was already on the OnConnected call
}
catch (Exception e)
{
LogError(e, "Failed to reconnect, will try again in {0} ms.", miliseconds * 2);
}
await Task.Delay(TimeSpan.FromMilliseconds(miliseconds));
miliseconds = Math.Min(60_000, Math.Pow(2, i) + 500);
i++;
return;
}
catch (Exception e)
{
LogError(e, "Failed to reconnect, will try again in {0} ms.", miliseconds * 2);
}
};
socket.ConnectAsync().Wait();
await Task.Delay(TimeSpan.FromMilliseconds(miliseconds));
_socket = socket;
}
miliseconds = Math.Min(60_000, Math.Pow(2, i) + 500);
i++;
}
};
Task.Run(async () =>
{
await socket.ConnectAsync();
_connectedSocketTask.TrySetResult(socket); //Probably was already on the OnConnected call
});
_socket = socket;
}
else
{
throw new Exception("Missing Socket Port");
}
}
else
{
throw new Exception("Missing Socket Port");
}
}
return _socket;
else
{
throw new Exception("Missing Socket Port");
}
}
}

View File

@@ -26,12 +26,12 @@
/// <summary>
/// Can be 0, 90, 180, 270, represents screen rotation in clock-wise degrees.
/// </summary>
public int Rotation { get; set; }
public float Rotation { get; set; }
/// <summary>
/// Output device's pixel scale factor.
/// </summary>
public int ScaleFactor { get; set; }
public float ScaleFactor { get; set; }
/// <summary>
/// Gets or sets the size.

View File

@@ -207,11 +207,5 @@ namespace ElectronNET.API.Entities
/// </value>
[DefaultValue(false)]
public bool WebviewTag { get; set; } = false;
/// <summary>
/// Whether to enable the remote module. Defaults to false.
/// </summary>
[DefaultValue(false)]
public bool EnableRemoteModule { get; set; } = false;
}
}

View File

@@ -37,6 +37,8 @@ namespace ElectronNET.API
}
}
public static bool IsConnected => BridgeConnector.IsConnected;
/// <summary>
/// Listens to channel, when a new message arrives listener would be called with
/// listener(event, args...).
@@ -62,7 +64,6 @@ namespace ElectronNET.API
});
}
/// <summary>
/// Listens to channel, when a new message arrives listener would be called with
/// listener(event, args...). This listner will keep the window event sender id
@@ -173,32 +174,28 @@ namespace ElectronNET.API
/// <param name="data">Arguments data.</param>
public void Send(BrowserWindow browserWindow, string channel, params object[] data)
{
List<JObject> jobjects = new List<JObject>();
List<JArray> jarrays = new List<JArray>();
List<object> objects = new List<object>();
var objectsWithCorrectSerialization = new List<object>();
objectsWithCorrectSerialization.Add(browserWindow.Id);
objectsWithCorrectSerialization.Add(channel);
foreach (var parameterObject in data)
{
if(parameterObject.GetType().IsArray || parameterObject.GetType().IsGenericType && parameterObject is IEnumerable)
{
jarrays.Add(JArray.FromObject(parameterObject, _jsonSerializer));
} else if(parameterObject.GetType().IsClass && !parameterObject.GetType().IsPrimitive && !(parameterObject is string))
objectsWithCorrectSerialization.Add(JArray.FromObject(parameterObject, _jsonSerializer));
}
else if(parameterObject.GetType().IsClass && !parameterObject.GetType().IsPrimitive && !(parameterObject is string))
{
jobjects.Add(JObject.FromObject(parameterObject, _jsonSerializer));
} else if(parameterObject.GetType().IsPrimitive || (parameterObject is string))
objectsWithCorrectSerialization.Add(JObject.FromObject(parameterObject, _jsonSerializer));
}
else if(parameterObject.GetType().IsPrimitive || (parameterObject is string))
{
objects.Add(parameterObject);
objectsWithCorrectSerialization.Add(parameterObject);
}
}
if(jobjects.Count > 0 || jarrays.Count > 0)
{
BridgeConnector.Emit("sendToIpcRenderer", JObject.FromObject(browserWindow, _jsonSerializer), channel, jarrays.ToArray(), jobjects.ToArray(), objects.ToArray());
}
else
{
BridgeConnector.Emit("sendToIpcRenderer", JObject.FromObject(browserWindow, _jsonSerializer), channel, data);
}
BridgeConnector.Emit("sendToIpcRenderer", objectsWithCorrectSerialization.ToArray());
}
/// <summary>

View File

@@ -40,7 +40,6 @@ namespace ElectronNET.API
return _windowManager;
}
}
private readonly SemaphoreSlim _singleCreate = new SemaphoreSlim(1, 1);
/// <summary>
/// Quit when all windows are closed. (Default is true)
@@ -96,76 +95,85 @@ namespace ElectronNET.API
/// <returns></returns>
public async Task<BrowserWindow> CreateWindowAsync(BrowserWindowOptions options, string loadUrl = "http://localhost")
{
await _singleCreate.WaitAsync();
BootstrapUpdateOpenIDsEvent();
try
var taskCompletionSource = new TaskCompletionSource<BrowserWindow>(TaskCreationOptions.RunContinuationsAsynchronously);
var guid = Guid.NewGuid().ToString();
BridgeConnector.Once<int>("BrowserWindowCreated" + guid, (id) =>
{
var taskCompletionSource = new TaskCompletionSource<BrowserWindow>(TaskCreationOptions.RunContinuationsAsynchronously);
var browserWindow = new BrowserWindow(id);
BridgeConnector.On<int>("BrowserWindowCreated", (id) =>
{
BridgeConnector.Off("BrowserWindowCreated");
_browserWindows[id] = browserWindow;
var browserWindow = new BrowserWindow(id);
taskCompletionSource.SetResult(browserWindow);
});
_browserWindows[id] = browserWindow;
taskCompletionSource.SetResult(browserWindow);
});
if (string.Equals(loadUrl, "HTTP://LOCALHOST", StringComparison.InvariantCultureIgnoreCase))
{
loadUrl = $"{loadUrl}:{BridgeSettings.WebPort}";
}
BridgeConnector.Off("BrowserWindowClosed");
BridgeConnector.On<int[]>("BrowserWindowClosed", (browserWindowIdsStillOpen) =>
{
if (browserWindowIdsStillOpen.Any())
{
foreach (var id in _browserWindows.Keys.ToArray())
{
if (!browserWindowIdsStillOpen.Contains(id)) _browserWindows.TryRemove(id, out _);
}
}
else
{
_browserWindows.Clear();
}
});
// Workaround Windows 10 / Electron Bug
// https://github.com/electron/electron/issues/4045
if (IsWindows10())
{
options.Width += 14;
options.Height += 7;
}
if (string.Equals(loadUrl, "HTTP://LOCALHOST", StringComparison.InvariantCultureIgnoreCase))
{
loadUrl = $"{loadUrl}:{BridgeSettings.WebPort}";
}
if (options.X == -1 && options.Y == -1)
{
options.X = 0;
options.Y = 0;
BridgeConnector.Emit("createBrowserWindow", guid, JObject.FromObject(options, _jsonSerializer), loadUrl);
}
else
{
// Workaround Windows 10 / Electron Bug
// https://github.com/electron/electron/issues/4045
if (IsWindows10())
{
options.Width = options.Width + 14;
options.Height = options.Height + 7;
options.X -= 7;
}
if (options.X == -1 && options.Y == -1)
{
options.X = 0;
options.Y = 0;
BridgeConnector.Emit("createBrowserWindow", JObject.FromObject(options, _jsonSerializer), loadUrl);
}
else
{
// Workaround Windows 10 / Electron Bug
// https://github.com/electron/electron/issues/4045
if (IsWindows10())
{
options.X = options.X - 7;
}
BridgeConnector.Emit("createBrowserWindow", JObject.FromObject(options, _keepDefaultValuesSerializer), loadUrl);
}
return await taskCompletionSource.Task;
BridgeConnector.Emit("createBrowserWindow", guid, JObject.FromObject(options, _keepDefaultValuesSerializer), loadUrl);
}
finally
return await taskCompletionSource.Task;
}
private bool _hasClosedEvent = false;
private readonly object _hasClosedEventLock = new();
private void BootstrapUpdateOpenIDsEvent()
{
if (!_hasClosedEvent)
{
_singleCreate.Release();
lock(_hasClosedEventLock)
{
if(!_hasClosedEvent)
{
BridgeConnector.On<int[]>("BrowserWindowUpdateOpenIDs", (browserWindowIdsStillOpen) =>
{
if (browserWindowIdsStillOpen.Any())
{
foreach (var id in _browserWindows.Keys.ToArray())
{
if (!browserWindowIdsStillOpen.Contains(id)) _browserWindows.TryRemove(id, out _);
}
}
else
{
_browserWindows.Clear();
}
});
_hasClosedEvent = true;
}
}
}
}
@@ -194,32 +202,20 @@ namespace ElectronNET.API
/// <returns></returns>
public async Task<BrowserView> CreateBrowserViewAsync(BrowserViewConstructorOptions options)
{
await _singleCreate.WaitAsync();
var guid = Guid.NewGuid().ToString();
try
var taskCompletionSource = new TaskCompletionSource<BrowserView>(TaskCreationOptions.RunContinuationsAsynchronously);
BridgeConnector.Once<int>("BrowserViewCreated" + guid, (id) =>
{
var browserView = new BrowserView(id);
_browserViews[id] = browserView;
taskCompletionSource.SetResult(browserView);
});
var taskCompletionSource = new TaskCompletionSource<BrowserView>(TaskCreationOptions.RunContinuationsAsynchronously);
BridgeConnector.Emit("createBrowserView", guid, JObject.FromObject(options, _keepDefaultValuesSerializer));
BridgeConnector.On<int>("BrowserViewCreated", (id) =>
{
BridgeConnector.Off("BrowserViewCreated");
BrowserView browserView = new BrowserView(id);
_browserViews[id] = browserView;
taskCompletionSource.SetResult(browserView);
});
BridgeConnector.Emit("createBrowserView", JObject.FromObject(options, _keepDefaultValuesSerializer));
return await taskCompletionSource.Task;
}
finally
{
_singleCreate.Release();
}
return await taskCompletionSource.Task;
}
private static JsonSerializer _jsonSerializer = new JsonSerializer()

View File

@@ -7,7 +7,7 @@ let browserView, electronSocket;
const proxyToCredentialsMap = (global['proxyToCredentialsMap'] = global['proxyToCredentialsMap'] || []);
const browserViewApi = (socket) => {
electronSocket = socket;
socket.on('createBrowserView', (options) => {
socket.on('createBrowserView', (guid, options) => {
if (!hasOwnChildreen(options, 'webPreferences', 'nodeIntegration')) {
options = { ...options, webPreferences: { nodeIntegration: true, contextIsolation: false } };
}
@@ -20,7 +20,7 @@ const browserViewApi = (socket) => {
proxyToCredentialsMap[options.proxy] = options.proxyCredentials;
}
browserViews.push(browserView);
electronSocket.emit('BrowserViewCreated', browserView['id']);
electronSocket.emit('BrowserViewCreated' + guid, browserView['id']);
});
socket.on('browserView-getBounds', (id) => {
const bounds = getBrowserViewById(id).getBounds();

View File

@@ -7,7 +7,7 @@ const proxyToCredentialsMap: { [proxy: string]: string } = (global['proxyToCrede
const browserViewApi = (socket: Socket) => {
electronSocket = socket;
socket.on('createBrowserView', (options) => {
socket.on('createBrowserView', (guid, options) => {
if (!hasOwnChildreen(options, 'webPreferences', 'nodeIntegration')) {
options = { ...options, webPreferences: { nodeIntegration: true, contextIsolation: false } };
}
@@ -25,7 +25,7 @@ const browserViewApi = (socket: Socket) => {
browserViews.push(browserView);
electronSocket.emit('BrowserViewCreated', browserView['id']);
electronSocket.emit('BrowserViewCreated' + guid, browserView['id']);
});
socket.on('browserView-getBounds', (id) => {

View File

@@ -175,7 +175,7 @@ module.exports = (socket, app) => {
electronSocket.emit('browserWindow-new-window-for-tab' + id);
});
});
socket.on('createBrowserWindow', (options, loadUrl) => {
socket.on('createBrowserWindow', (guid, options, loadUrl) => {
if (options.webPreferences && !('nodeIntegration' in options.webPreferences)) {
options = { ...options, webPreferences: { ...options.webPreferences, nodeIntegration: true, contextIsolation: false } };
}
@@ -188,7 +188,7 @@ module.exports = (socket, app) => {
if (window) {
window.reload();
windows.push(window);
electronSocket.emit('BrowserWindowCreated', window.id);
electronSocket.emit('BrowserWindowCreated' + guid, window.id);
return;
}
}
@@ -218,6 +218,7 @@ module.exports = (socket, app) => {
readyToShowWindowsIds.push(window.id);
}
});
window.on('closed', (sender) => {
again:
for (let index = 0; index < windows.length; index++) {
@@ -234,7 +235,7 @@ module.exports = (socket, app) => {
}
const ids = [];
windows.forEach(x => ids.push(x.id));
electronSocket.emit('BrowserWindowClosed', ids);
electronSocket.emit('BrowserWindowUpdateOpenIDs', ids);
});
if (loadUrl) {
window.loadURL(loadUrl);
@@ -250,7 +251,7 @@ module.exports = (socket, app) => {
app['mainWindow'] = window;
}
windows.push(window);
electronSocket.emit('BrowserWindowCreated', window.id);
electronSocket.emit('BrowserWindowCreated' + guid, window.id);
});
socket.on('browserWindowDestroy', (id) => {
getWindowById(id)?.destroy();

View File

@@ -209,7 +209,7 @@ export = (socket: Socket, app: Electron.App) => {
});
});
socket.on('createBrowserWindow', (options, loadUrl) => {
socket.on('createBrowserWindow', (guid, options, loadUrl) => {
if (options.webPreferences && !('nodeIntegration' in options.webPreferences)) {
options = { ...options, webPreferences: { ...options.webPreferences, nodeIntegration: true, contextIsolation: false } };
} else if (!options.webPreferences) {
@@ -222,7 +222,7 @@ export = (socket: Socket, app: Electron.App) => {
if (window) {
window.reload();
windows.push(window);
electronSocket.emit('BrowserWindowCreated', window.id);
electronSocket.emit('BrowserWindowCreated' + guid, window.id);
return;
}
} else {
@@ -261,7 +261,7 @@ export = (socket: Socket, app: Electron.App) => {
}
const ids = [];
windows.forEach(x => ids.push(x.id));
electronSocket.emit('BrowserWindowClosed', ids);
electronSocket.emit('BrowserWindowUpdateOpenIDs', ids);
});
if (loadUrl) {
@@ -281,7 +281,7 @@ export = (socket: Socket, app: Electron.App) => {
}
windows.push(window);
electronSocket.emit('BrowserWindowCreated', window.id);
electronSocket.emit('BrowserWindowCreated' + guid, window.id);
});
socket.on('browserWindowDestroy', (id) => {

View File

@@ -38,8 +38,8 @@ module.exports = (socket) => {
socket.on('removeAllListenersIpcMainChannel', (channel) => {
electron_1.ipcMain.removeAllListeners(channel);
});
socket.on('sendToIpcRenderer', (browserWindow, channel, ...data) => {
const window = electron_1.BrowserWindow.fromId(browserWindow.id);
socket.on('sendToIpcRenderer', (browserWindowId, channel, ...data) => {
const window = electron_1.BrowserWindow.fromId(browserWindowId);
if (window) {
window.webContents.send(channel, ...data);
}

View File

@@ -44,8 +44,8 @@ export = (socket: Socket) => {
ipcMain.removeAllListeners(channel);
});
socket.on('sendToIpcRenderer', (browserWindow, channel, ...data) => {
const window = BrowserWindow.fromId(browserWindow.id);
socket.on('sendToIpcRenderer', (browserWindowId, channel, ...data) => {
const window = BrowserWindow.fromId(browserWindowId);
if (window) {
window.webContents.send(channel, ...data);

View File

@@ -31,9 +31,9 @@
}
},
"@electron/get": {
"version": "1.12.4",
"resolved": "https://registry.npmjs.org/@electron/get/-/get-1.12.4.tgz",
"integrity": "sha512-6nr9DbJPUR9Xujw6zD3y+rS95TyItEVM0NVjt1EehY2vUWfIgPiIPVHxCvaTS0xr2B+DRxovYVKbuOWqC35kjg==",
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/@electron/get/-/get-1.13.0.tgz",
"integrity": "sha512-+SjZhRuRo+STTO1Fdhzqnv9D2ZhjxXP6egsJ9kiO8dtP68cDx7dFCwWi64dlMQV7sWcfW1OYCW4wviEBzmRsfQ==",
"dev": true,
"requires": {
"debug": "^4.1.1",
@@ -71,9 +71,9 @@
}
},
"@types/node": {
"version": "15.14.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-15.14.0.tgz",
"integrity": "sha512-um/+/ip3QZmwLfIkWZSNtQIJNVAqrJ92OkLMeuZrjZMTAJniI7fh8N8OICyDhAJ2mzgk/fmYFo72jRr5HyZ1EQ==",
"version": "15.14.9",
"resolved": "https://registry.npmjs.org/@types/node/-/node-15.14.9.tgz",
"integrity": "sha512-qjd88DrCxupx/kJD5yQgZdcYKZKSIGBVDIBE1/LTGcNm3d2Np/jxojkdePDdfnBHJc5W7vSMpbJ1aB7p/Py69A==",
"dev": true
},
"@types/semver": {
@@ -153,9 +153,9 @@
"integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig=="
},
"boolean": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/boolean/-/boolean-3.1.2.tgz",
"integrity": "sha512-YN6UmV0FfLlBVvRvNPx3pz5W/mUoYB24J4WSXOKP/OOJpi+Oq6WYqPaNTHzjI0QzwWtnvEd5CGYyQPgp1jFxnw==",
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/boolean/-/boolean-3.1.4.tgz",
"integrity": "sha512-3hx0kwU3uzG6ReQ3pnaFQPSktpBw6RHN3/ivDKEuU8g1XSfafowyvDnadjv1xp8IZqhtSukxlwv9bF6FhX8m0w==",
"dev": true,
"optional": true
},
@@ -176,9 +176,9 @@
"dev": true
},
"buffer-from": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"dev": true
},
"builder-util-runtime": {
@@ -337,16 +337,16 @@
"integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA=="
},
"core-js": {
"version": "3.15.2",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.15.2.tgz",
"integrity": "sha512-tKs41J7NJVuaya8DxIOCnl8QuPHx5/ZVbFo1oKgVl1qHFBBrDctzQGtuLjPpRdNTWmKPH6oEvgN/MUID+l485Q==",
"version": "3.17.1",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.17.1.tgz",
"integrity": "sha512-C8i/FNpVN2Ti89QIJcFn9ZQmnM+HaAQr2OpE+ja3TRM9Q34FigsGlAVuwPGkIgydSVClo/1l1D1grP8LVt9IYA==",
"dev": true,
"optional": true
},
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
"dev": true
},
"dasherize": {
@@ -355,9 +355,9 @@
"integrity": "sha1-bYCcnNDPe7iVLYD8hPoT1H3bEwg="
},
"debug": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
"integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
"dev": true,
"requires": {
"ms": "2.1.2"
@@ -408,9 +408,9 @@
"dev": true
},
"electron": {
"version": "13.1.5",
"resolved": "https://registry.npmjs.org/electron/-/electron-13.1.5.tgz",
"integrity": "sha512-ZoMCcPQNs/zO/Zdb5hq5H+rwRaKrdI3/sfXEwBVMx7f5jwa9jPQB3dZ2+7t59uD9VcFAWsH/pozr8nPPlv0tyw==",
"version": "14.0.0",
"resolved": "https://registry.npmjs.org/electron/-/electron-14.0.0.tgz",
"integrity": "sha512-O6EI7L1BPIrTpEIFefjjmdbmSn9LtE4mmrv4dfpV4Mqaa8uKuNYQogwZPEvSwaBexb69eb1LQ25n+f+kBcjiRQ==",
"dev": true,
"requires": {
"@electron/get": "^1.0.1",
@@ -419,9 +419,9 @@
},
"dependencies": {
"@types/node": {
"version": "14.17.4",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.4.tgz",
"integrity": "sha512-8kQ3+wKGRNN0ghtEn7EGps/B8CzuBz1nXZEIGGLP2GnwbqYn4dbTs7k+VKLTq1HvZLRCIDtN3Snx1Ege8B7L5A==",
"version": "14.17.14",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.14.tgz",
"integrity": "sha512-rsAj2u8Xkqfc332iXV12SqIsjVi07H479bOP4q94NAcjzmAvapumEhuVIt53koEf7JFrpjgNKjBga5Pnn/GL8A==",
"dev": true
}
}
@@ -1410,9 +1410,9 @@
"dev": true
},
"typescript": {
"version": "4.3.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz",
"integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==",
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.2.tgz",
"integrity": "sha512-gzP+t5W4hdy4c+68bfcv0t400HVJMMd2+H9B7gae1nQlBzCqvrXX+6GL/b3GAgyTH966pzrZ70/fRjwAtZksSQ==",
"dev": true
},
"universalify": {

View File

@@ -19,9 +19,9 @@
"socket.io": "^2.4.0"
},
"devDependencies": {
"@types/node": "^15.14.0",
"electron": "^13.1.5",
"@types/node": "^15.14.9",
"electron": "^14.0.0",
"tslint": "^6.1.3",
"typescript": "^4.3.5"
"typescript": "^4.4.2"
}
}