mirror of
https://github.com/frappe/books.git
synced 2024-11-12 16:36:27 +00:00
refactor: shift main process stuff out of source
This commit is contained in:
parent
761dd641bf
commit
a596f5dcad
153
main.ts
Normal file
153
main.ts
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
import {
|
||||||
|
app,
|
||||||
|
BrowserWindow,
|
||||||
|
BrowserWindowConstructorOptions,
|
||||||
|
protocol,
|
||||||
|
} from 'electron';
|
||||||
|
import Store from 'electron-store';
|
||||||
|
import { autoUpdater } from 'electron-updater';
|
||||||
|
import path from 'path';
|
||||||
|
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib';
|
||||||
|
import { getMainWindowSize } from './main/helpers';
|
||||||
|
import registerAppLifecycleListeners from './main/registerAppLifecycleListeners';
|
||||||
|
import registerAutoUpdaterListeners from './main/registerAutoUpdaterListeners';
|
||||||
|
import registerIpcMainActionListeners from './main/registerIpcMainActionListeners';
|
||||||
|
import registerIpcMainMessageListeners from './main/registerIpcMainMessageListeners';
|
||||||
|
import registerProcessListeners from './main/registerProcessListeners';
|
||||||
|
import { IPC_CHANNELS } from './src/messages';
|
||||||
|
|
||||||
|
export class Main {
|
||||||
|
title: string = 'Frappe Books';
|
||||||
|
icon: string;
|
||||||
|
|
||||||
|
winURL: string = '';
|
||||||
|
isWebpackUrl: boolean = false;
|
||||||
|
checkedForUpdate = false;
|
||||||
|
mainWindow: BrowserWindow | null = null;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.icon = this.isDevelopment
|
||||||
|
? path.resolve('./build/icon.png')
|
||||||
|
: path.join(__dirname, 'icons', '512x512.png');
|
||||||
|
|
||||||
|
protocol.registerSchemesAsPrivileged([
|
||||||
|
{ scheme: 'app', privileges: { secure: true, standard: true } },
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (this.isDevelopment) {
|
||||||
|
autoUpdater.logger = console;
|
||||||
|
}
|
||||||
|
|
||||||
|
Store.initRenderer();
|
||||||
|
|
||||||
|
this.registerListeners();
|
||||||
|
if (this.isMac && this.isDevelopment) {
|
||||||
|
app.dock.setIcon(this.icon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get isDevelopment() {
|
||||||
|
return process.env.NODE_ENV !== 'production';
|
||||||
|
}
|
||||||
|
|
||||||
|
get isMac() {
|
||||||
|
return process.platform === 'darwin';
|
||||||
|
}
|
||||||
|
|
||||||
|
get isLinux() {
|
||||||
|
return process.platform === 'linux';
|
||||||
|
}
|
||||||
|
|
||||||
|
registerListeners() {
|
||||||
|
registerIpcMainMessageListeners(this);
|
||||||
|
registerIpcMainActionListeners(this);
|
||||||
|
registerAutoUpdaterListeners(this);
|
||||||
|
registerAppLifecycleListeners(this);
|
||||||
|
registerProcessListeners(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
getOptions(): BrowserWindowConstructorOptions {
|
||||||
|
const { width, height } = getMainWindowSize();
|
||||||
|
const options: BrowserWindowConstructorOptions = {
|
||||||
|
vibrancy: 'sidebar',
|
||||||
|
transparent: this.isMac,
|
||||||
|
backgroundColor: '#80FFFFFF',
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
title: this.title,
|
||||||
|
webPreferences: {
|
||||||
|
contextIsolation: false, // TODO: Switch this off
|
||||||
|
nodeIntegration: process.env
|
||||||
|
.ELECTRON_NODE_INTEGRATION as unknown as boolean,
|
||||||
|
},
|
||||||
|
frame: this.isLinux,
|
||||||
|
resizable: true,
|
||||||
|
};
|
||||||
|
if (this.isDevelopment || this.isLinux) {
|
||||||
|
Object.assign(options, { icon: this.icon });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isLinux) {
|
||||||
|
Object.assign(options, {
|
||||||
|
icon: path.join(__dirname, '/icons/512x512.png'),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
createWindow() {
|
||||||
|
const options = this.getOptions();
|
||||||
|
this.mainWindow = new BrowserWindow(options);
|
||||||
|
|
||||||
|
this.isWebpackUrl = !!process.env.WEBPACK_DEV_SERVER_URL;
|
||||||
|
if (this.isWebpackUrl) {
|
||||||
|
this.loadWebpackDevServerURL();
|
||||||
|
} else {
|
||||||
|
this.loadAppUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setMainWindowListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
loadWebpackDevServerURL() {
|
||||||
|
// Load the url of the dev server if in development mode
|
||||||
|
this.winURL = process.env.WEBPACK_DEV_SERVER_URL as string;
|
||||||
|
this.mainWindow!.loadURL(this.winURL);
|
||||||
|
|
||||||
|
if (!process.env.IS_TEST) {
|
||||||
|
this.mainWindow!.webContents.openDevTools();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loadAppUrl() {
|
||||||
|
createProtocol('app');
|
||||||
|
// Load the index.html when not in development
|
||||||
|
this.winURL = 'app://./index.html';
|
||||||
|
this.mainWindow!.loadURL(this.winURL);
|
||||||
|
}
|
||||||
|
|
||||||
|
setMainWindowListeners() {
|
||||||
|
if (this.mainWindow === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.mainWindow.on('closed', () => {
|
||||||
|
this.mainWindow = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.mainWindow.webContents.on('did-finish-load', () => {
|
||||||
|
if (this.mainWindow === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.mainWindow.webContents.send(IPC_CHANNELS.STORE_ON_WINDOW, {
|
||||||
|
appVersion: app.getVersion(),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new Main();
|
14
main/helpers.ts
Normal file
14
main/helpers.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import electron, { app } from 'electron';
|
||||||
|
|
||||||
|
export function getMainWindowSize() {
|
||||||
|
let height;
|
||||||
|
if (app.isReady()) {
|
||||||
|
const screen = electron.screen;
|
||||||
|
height = screen.getPrimaryDisplay().workAreaSize.height;
|
||||||
|
height = height > 907 ? 907 : height;
|
||||||
|
} else {
|
||||||
|
height = 907;
|
||||||
|
}
|
||||||
|
const width = Math.ceil(1.323 * height);
|
||||||
|
return { height, width };
|
||||||
|
}
|
32
main/registerAppLifecycleListeners.ts
Normal file
32
main/registerAppLifecycleListeners.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { app } from 'electron';
|
||||||
|
import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer';
|
||||||
|
import { Main } from '../main';
|
||||||
|
|
||||||
|
export default function registerAppLifecycleListeners(main: Main) {
|
||||||
|
app.on('window-all-closed', () => {
|
||||||
|
if (process.platform !== 'darwin') {
|
||||||
|
app.quit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.on('activate', () => {
|
||||||
|
if (main.mainWindow === null) {
|
||||||
|
main.createWindow();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.on('ready', async () => {
|
||||||
|
if (main.isDevelopment && !process.env.IS_TEST) {
|
||||||
|
try {
|
||||||
|
await installExtension(VUEJS_DEVTOOLS);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(
|
||||||
|
'Vue Devtools failed to install:',
|
||||||
|
(e as Error).toString()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main.createWindow();
|
||||||
|
});
|
||||||
|
}
|
49
main/registerAutoUpdaterListeners.ts
Normal file
49
main/registerAutoUpdaterListeners.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import { autoUpdater, UpdateInfo } from 'electron-updater';
|
||||||
|
import { Main } from '../main';
|
||||||
|
import { IPC_CHANNELS } from '../src/messages';
|
||||||
|
|
||||||
|
export default function registerAutoUpdaterListeners(main: Main) {
|
||||||
|
autoUpdater.autoDownload = false;
|
||||||
|
autoUpdater.autoInstallOnAppQuit = false;
|
||||||
|
|
||||||
|
autoUpdater.on('checking-for-update', () => {
|
||||||
|
if (!main.checkedForUpdate) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
main.mainWindow!.webContents.send(IPC_CHANNELS.CHECKING_FOR_UPDATE);
|
||||||
|
});
|
||||||
|
|
||||||
|
autoUpdater.on('update-available', (info: UpdateInfo) => {
|
||||||
|
if (!main.checkedForUpdate) {
|
||||||
|
main.checkedForUpdate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
main.mainWindow!.webContents.send(
|
||||||
|
IPC_CHANNELS.UPDATE_AVAILABLE,
|
||||||
|
info.version
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
autoUpdater.on('update-not-available', () => {
|
||||||
|
if (!main.checkedForUpdate) {
|
||||||
|
main.checkedForUpdate = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
main.mainWindow!.webContents.send(IPC_CHANNELS.UPDATE_NOT_AVAILABLE);
|
||||||
|
});
|
||||||
|
|
||||||
|
autoUpdater.on('update-downloaded', () => {
|
||||||
|
main.mainWindow!.webContents.send(IPC_CHANNELS.UPDATE_DOWNLOADED);
|
||||||
|
});
|
||||||
|
|
||||||
|
autoUpdater.on('error', (error) => {
|
||||||
|
if (!main.checkedForUpdate) {
|
||||||
|
main.checkedForUpdate = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
main.mainWindow!.webContents.send(IPC_CHANNELS.UPDATE_ERROR, error);
|
||||||
|
});
|
||||||
|
}
|
115
main/registerIpcMainActionListeners.ts
Normal file
115
main/registerIpcMainActionListeners.ts
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
import { dialog, ipcMain } from 'electron';
|
||||||
|
import { autoUpdater } from 'electron-updater';
|
||||||
|
import fs from 'fs/promises';
|
||||||
|
import path from 'path';
|
||||||
|
import { Main } from '../main';
|
||||||
|
import { getUrlAndTokenString, sendError } from '../src/contactMothership';
|
||||||
|
import { getLanguageMap } from '../src/getLanguageMap';
|
||||||
|
import { IPC_ACTIONS } from '../src/messages';
|
||||||
|
import saveHtmlAsPdf from '../src/saveHtmlAsPdf';
|
||||||
|
import { getMainWindowSize } from './helpers';
|
||||||
|
|
||||||
|
export default function registerIpcMainActionListeners(main: Main) {
|
||||||
|
ipcMain.handle(IPC_ACTIONS.TOGGLE_MAXIMIZE_CURRENT_WINDOW, (event) => {
|
||||||
|
const maximizing = main.mainWindow!.isMaximized();
|
||||||
|
if (maximizing) {
|
||||||
|
main.mainWindow!.maximize();
|
||||||
|
} else {
|
||||||
|
main.mainWindow!.unmaximize();
|
||||||
|
}
|
||||||
|
return maximizing;
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.handle(IPC_ACTIONS.GET_OPEN_FILEPATH, async (event, options) => {
|
||||||
|
return await dialog.showOpenDialog(main.mainWindow!, options);
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.handle(IPC_ACTIONS.GET_SAVE_FILEPATH, async (event, options) => {
|
||||||
|
return await dialog.showSaveDialog(main.mainWindow!, options);
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.handle(IPC_ACTIONS.GET_PRIMARY_DISPLAY_SIZE, (event) => {
|
||||||
|
return getMainWindowSize();
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.handle(IPC_ACTIONS.GET_DIALOG_RESPONSE, async (event, options) => {
|
||||||
|
if (main.isDevelopment || main.isLinux) {
|
||||||
|
Object.assign(options, { icon: main.icon });
|
||||||
|
}
|
||||||
|
|
||||||
|
return await dialog.showMessageBox(main.mainWindow!, options);
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.handle(IPC_ACTIONS.SHOW_ERROR, async (event, { title, content }) => {
|
||||||
|
return await dialog.showErrorBox(title, content);
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.handle(
|
||||||
|
IPC_ACTIONS.SAVE_HTML_AS_PDF,
|
||||||
|
async (event, html, savePath) => {
|
||||||
|
return await saveHtmlAsPdf(html, savePath);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
ipcMain.handle(IPC_ACTIONS.SAVE_DATA, async (event, data, savePath) => {
|
||||||
|
return await fs.writeFile(savePath, data, { encoding: 'utf-8' });
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.handle(IPC_ACTIONS.SEND_ERROR, (event, bodyJson) => {
|
||||||
|
sendError(bodyJson);
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.handle(IPC_ACTIONS.CHECK_FOR_UPDATES, (event, force) => {
|
||||||
|
if (!main.isDevelopment && !main.checkedForUpdate) {
|
||||||
|
autoUpdater.checkForUpdates();
|
||||||
|
} else if (force) {
|
||||||
|
autoUpdater.checkForUpdates();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.handle(IPC_ACTIONS.GET_LANGUAGE_MAP, async (event, code) => {
|
||||||
|
const obj = { languageMap: {}, success: true, message: '' };
|
||||||
|
try {
|
||||||
|
obj.languageMap = await getLanguageMap(code, main.isDevelopment);
|
||||||
|
} catch (err) {
|
||||||
|
obj.success = false;
|
||||||
|
obj.message = (err as Error).message;
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.handle(IPC_ACTIONS.GET_FILE, async (event, options) => {
|
||||||
|
const response = {
|
||||||
|
name: '',
|
||||||
|
filePath: '',
|
||||||
|
success: false,
|
||||||
|
data: Buffer.from('', 'utf-8'),
|
||||||
|
canceled: false,
|
||||||
|
};
|
||||||
|
const { filePaths, canceled } = await dialog.showOpenDialog(
|
||||||
|
main.mainWindow!,
|
||||||
|
options
|
||||||
|
);
|
||||||
|
|
||||||
|
response.filePath = filePaths?.[0];
|
||||||
|
response.canceled = canceled;
|
||||||
|
|
||||||
|
if (!response.filePath) {
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
response.success = true;
|
||||||
|
if (canceled) {
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
response.name = path.basename(response.filePath);
|
||||||
|
response.data = await fs.readFile(response.filePath);
|
||||||
|
return response;
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.handle(IPC_ACTIONS.GET_CREDS, async (event) => {
|
||||||
|
return await getUrlAndTokenString();
|
||||||
|
});
|
||||||
|
}
|
54
main/registerIpcMainMessageListeners.ts
Normal file
54
main/registerIpcMainMessageListeners.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import { ipcMain, Menu, shell } from 'electron';
|
||||||
|
import { autoUpdater } from 'electron-updater';
|
||||||
|
import { Main } from '../main';
|
||||||
|
import { IPC_MESSAGES } from '../src/messages';
|
||||||
|
|
||||||
|
export default function registerIpcMainMessageListeners(main: Main) {
|
||||||
|
ipcMain.on(IPC_MESSAGES.OPEN_MENU, (event) => {
|
||||||
|
if (event.sender === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const menu = Menu.getApplicationMenu();
|
||||||
|
if (menu === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
menu.popup({ window: main.mainWindow! });
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.on(IPC_MESSAGES.RELOAD_MAIN_WINDOW, () => {
|
||||||
|
main.mainWindow!.reload();
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.on(IPC_MESSAGES.RESIZE_MAIN_WINDOW, (event, size, resizable) => {
|
||||||
|
const [width, height] = size;
|
||||||
|
if (!width || !height) return;
|
||||||
|
main.mainWindow!.setSize(width, height);
|
||||||
|
main.mainWindow!.setResizable(resizable);
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.on(IPC_MESSAGES.CLOSE_CURRENT_WINDOW, (event) => {
|
||||||
|
main.mainWindow!.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.on(IPC_MESSAGES.MINIMIZE_CURRENT_WINDOW, (event) => {
|
||||||
|
main.mainWindow!.minimize();
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.on(IPC_MESSAGES.OPEN_EXTERNAL, (event, link) => {
|
||||||
|
shell.openExternal(link);
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.on(IPC_MESSAGES.SHOW_ITEM_IN_FOLDER, (event, filePath) => {
|
||||||
|
return shell.showItemInFolder(filePath);
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.on(IPC_MESSAGES.DOWNLOAD_UPDATE, (event) => {
|
||||||
|
autoUpdater.downloadUpdate();
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.on(IPC_MESSAGES.INSTALL_UPDATE, (event) => {
|
||||||
|
autoUpdater.quitAndInstall(true, true);
|
||||||
|
});
|
||||||
|
}
|
18
main/registerProcessListeners.ts
Normal file
18
main/registerProcessListeners.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { app } from 'electron';
|
||||||
|
import { Main } from '../main';
|
||||||
|
|
||||||
|
export default function registerProcessListeners(main: Main) {
|
||||||
|
if (main.isDevelopment) {
|
||||||
|
if (process.platform === 'win32') {
|
||||||
|
process.on('message', (data) => {
|
||||||
|
if (data === 'graceful-exit') {
|
||||||
|
app.quit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
process.on('SIGTERM', () => {
|
||||||
|
app.quit();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -16,7 +16,6 @@
|
|||||||
"postuninstall": "electron-builder install-app-deps",
|
"postuninstall": "electron-builder install-app-deps",
|
||||||
"script:translate": "node scripts/generateTranslations.js"
|
"script:translate": "node scripts/generateTranslations.js"
|
||||||
},
|
},
|
||||||
"main": "background.js",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@popperjs/core": "^2.10.2",
|
"@popperjs/core": "^2.10.2",
|
||||||
"core-js": "^3.19.0",
|
"core-js": "^3.19.0",
|
||||||
@ -35,6 +34,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.16.0",
|
"@babel/core": "^7.16.0",
|
||||||
"@babel/eslint-parser": "^7.16.0",
|
"@babel/eslint-parser": "^7.16.0",
|
||||||
|
"@types/electron-devtools-installer": "^2.2.0",
|
||||||
"@types/lodash": "^4.14.179",
|
"@types/lodash": "^4.14.179",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.15.1",
|
"@typescript-eslint/eslint-plugin": "^4.15.1",
|
||||||
"@typescript-eslint/parser": "^4.15.1",
|
"@typescript-eslint/parser": "^4.15.1",
|
||||||
@ -69,11 +69,11 @@
|
|||||||
"singleQuote": true,
|
"singleQuote": true,
|
||||||
"trailingComma": "es5"
|
"trailingComma": "es5"
|
||||||
},
|
},
|
||||||
|
"engineStrict": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.13.1 <17",
|
"node": ">=16.13.1 <17",
|
||||||
"yarn": "1.22.17"
|
"yarn": "1.22.17"
|
||||||
},
|
},
|
||||||
"engineStrict": true,
|
|
||||||
"gitHooks": {
|
"gitHooks": {
|
||||||
"pre-commit": "lint-staged"
|
"pre-commit": "lint-staged"
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "esnext",
|
"target": "es2018",
|
||||||
"module": "esnext",
|
"module": "esnext",
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
|
@ -5,6 +5,7 @@ module.exports = {
|
|||||||
pluginOptions: {
|
pluginOptions: {
|
||||||
electronBuilder: {
|
electronBuilder: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true,
|
||||||
|
mainProcessFile: 'main.ts',
|
||||||
disableMainProcessTypescript: false,
|
disableMainProcessTypescript: false,
|
||||||
mainProcessTypeChecking: true,
|
mainProcessTypeChecking: true,
|
||||||
chainWebpackRendererProcess: (config) => {
|
chainWebpackRendererProcess: (config) => {
|
||||||
|
@ -1221,6 +1221,11 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/ms" "*"
|
"@types/ms" "*"
|
||||||
|
|
||||||
|
"@types/electron-devtools-installer@^2.2.0":
|
||||||
|
version "2.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/electron-devtools-installer/-/electron-devtools-installer-2.2.1.tgz#27cd1e0a612ef070d980555ae32db5898649e813"
|
||||||
|
integrity sha512-V/gyryjHZi27/VeU5JtO89rqqq7w7d+Is0VYNLseARvR6ad7lXi8UCIJI9NraqNmd1NoGYedB1+tm5Q8UySF8A==
|
||||||
|
|
||||||
"@types/eslint-scope@^3.7.0":
|
"@types/eslint-scope@^3.7.0":
|
||||||
version "3.7.2"
|
version "3.7.2"
|
||||||
resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.2.tgz#11e96a868c67acf65bf6f11d10bb89ea71d5e473"
|
resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.2.tgz#11e96a868c67acf65bf6f11d10bb89ea71d5e473"
|
||||||
|
Loading…
Reference in New Issue
Block a user