From b99c2cf228e15d8e138a23d7b3dae277ed89d8e3 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Fri, 1 Mar 2024 17:25:20 +0100 Subject: [PATCH 1/6] [TS migration] Migrate 'Desktop' files --- config/webpack/webpack.desktop.js | 4 +- ...{ELECTRON_EVENTS.js => ELECTRON_EVENTS.ts} | 4 +- desktop/README.md | 4 +- desktop/contextBridge.js | 98 ---------- desktop/contextBridge.ts | 82 ++++++++ desktop/{main.js => main.ts} | 178 ++++++++++-------- desktop/{start.js => start.ts} | 9 +- package.json | 2 +- src/types/modules/electron.d.ts | 9 +- 9 files changed, 195 insertions(+), 195 deletions(-) rename desktop/{ELECTRON_EVENTS.js => ELECTRON_EVENTS.ts} (90%) delete mode 100644 desktop/contextBridge.js create mode 100644 desktop/contextBridge.ts rename desktop/{main.js => main.ts} (82%) rename desktop/{start.js => start.ts} (88%) diff --git a/config/webpack/webpack.desktop.js b/config/webpack/webpack.desktop.js index 2612e2b190fa..20ee4a4025df 100644 --- a/config/webpack/webpack.desktop.js +++ b/config/webpack/webpack.desktop.js @@ -28,8 +28,8 @@ module.exports = (env) => { name: 'desktop-main', target: 'electron-main', entry: { - main: './desktop/main.js', - contextBridge: './desktop/contextBridge.js', + main: './desktop/main.ts', + contextBridge: './desktop/contextBridge.ts', }, output: { filename: '[name].js', diff --git a/desktop/ELECTRON_EVENTS.js b/desktop/ELECTRON_EVENTS.ts similarity index 90% rename from desktop/ELECTRON_EVENTS.js rename to desktop/ELECTRON_EVENTS.ts index ee8c0521892e..de0bd655e12c 100644 --- a/desktop/ELECTRON_EVENTS.js +++ b/desktop/ELECTRON_EVENTS.ts @@ -9,6 +9,6 @@ const ELECTRON_EVENTS = { KEYBOARD_SHORTCUTS_PAGE: 'keyboard-shortcuts-page', START_UPDATE: 'start-update', UPDATE_DOWNLOADED: 'update-downloaded', -}; +} as const; -module.exports = ELECTRON_EVENTS; +export default ELECTRON_EVENTS; diff --git a/desktop/README.md b/desktop/README.md index 77abff97a898..4493196b5ed4 100644 --- a/desktop/README.md +++ b/desktop/README.md @@ -31,7 +31,7 @@ The New Expensify desktop app is built using [Electron.js](https://www.electronj The desktop app is organized in three pieces: 1. The Electron main process - - Implemented in https://github.com/Expensify/App/blob/main/desktop/main.js. + - Implemented in https://github.com/Expensify/App/blob/main/desktop/main.ts. - This file has access to the full set of Electron and Node.JS APIs. 2. The Electron renderer process - This is the webpack-bundled version of our react-native-web app (except using `index.desktop.js` files instead of `index.website.js`, where applicable) @@ -131,7 +131,7 @@ The root [package.json](../package.json) serves for `devDependencies` and shared The [desktop/package.json](./package.json) serves for desktop (electron-main) specific dependencies We use Webpack with a [desktop specific config](../config/webpack/webpack.desktop.js) to bundle our js code Half of the config takes care of packaging root package dependencies - everything related to rendering App in the Electron window. Packaged under `dist/www` -The other half is about bundling the `main.js` script which initializes Electron and renders `www` +The other half is about bundling the `main.ts` script which initializes Electron and renders `www` ## See what is getting packaged in the app If you suspect unnecessary items might be getting packaged you can inspect the package content in `desktop-build/` diff --git a/desktop/contextBridge.js b/desktop/contextBridge.js deleted file mode 100644 index a8b89cdc0b64..000000000000 --- a/desktop/contextBridge.js +++ /dev/null @@ -1,98 +0,0 @@ -const _ = require('underscore'); -const {contextBridge, ipcRenderer} = require('electron'); -const ELECTRON_EVENTS = require('./ELECTRON_EVENTS'); - -const WHITELIST_CHANNELS_RENDERER_TO_MAIN = [ - ELECTRON_EVENTS.REQUEST_DEVICE_ID, - ELECTRON_EVENTS.REQUEST_FOCUS_APP, - ELECTRON_EVENTS.REQUEST_UPDATE_BADGE_COUNT, - ELECTRON_EVENTS.REQUEST_VISIBILITY, - ELECTRON_EVENTS.START_UPDATE, - ELECTRON_EVENTS.LOCALE_UPDATED, -]; - -const WHITELIST_CHANNELS_MAIN_TO_RENDERER = [ELECTRON_EVENTS.KEYBOARD_SHORTCUTS_PAGE, ELECTRON_EVENTS.UPDATE_DOWNLOADED, ELECTRON_EVENTS.FOCUS, ELECTRON_EVENTS.BLUR]; - -const getErrorMessage = (channel) => `Electron context bridge cannot be used with channel '${channel}'`; - -/** - * The following methods will be available in the renderer process under `window.electron`. - */ -contextBridge.exposeInMainWorld('electron', { - /** - * Send data asynchronously from renderer process to main process. - * Note that this is a one-way channel – main will not respond. In order to get a response from main, either: - * - * - Use `sendSync` - * - Or implement `invoke` if you want to maintain asynchronous communication: https://www.electronjs.org/docs/latest/api/ipc-renderer#ipcrendererinvokechannel-args - * - * @param {String} channel - * @param {*} data - */ - send: (channel, data) => { - if (!_.contains(WHITELIST_CHANNELS_RENDERER_TO_MAIN, channel)) { - throw new Error(getErrorMessage(channel)); - } - - ipcRenderer.send(channel, data); - }, - - /** - * Send data synchronously from renderer process to main process. Main process may return a result. - * - * @param {String} channel - * @param {*} data - * @returns {*} - */ - sendSync: (channel, data) => { - if (!_.contains(WHITELIST_CHANNELS_RENDERER_TO_MAIN, channel)) { - throw new Error(getErrorMessage(channel)); - } - - return ipcRenderer.sendSync(channel, data); - }, - - /** - * Execute a function in the main process and return a promise that resolves with its response. - * - * @param {String} channel - * @param {*} args - * @returns {Promise} - */ - invoke: (channel, ...args) => { - if (!_.contains(WHITELIST_CHANNELS_RENDERER_TO_MAIN, channel)) { - throw new Error(getErrorMessage(channel)); - } - - return ipcRenderer.invoke(channel, ...args); - }, - - /** - * Set up a listener for events emitted from the main process and sent to the renderer process. - * - * @param {String} channel - * @param {Function} func - */ - on: (channel, func) => { - if (!_.contains(WHITELIST_CHANNELS_MAIN_TO_RENDERER, channel)) { - throw new Error(getErrorMessage(channel)); - } - - // Deliberately strip event as it includes `sender` - ipcRenderer.on(channel, (event, ...args) => func(...args)); - }, - - /** - * Remove listeners for a single channel from the main process and sent to the renderer process. - * - * @param {String} channel - * @param {Function} func - */ - removeAllListeners: (channel) => { - if (!_.contains(WHITELIST_CHANNELS_MAIN_TO_RENDERER, channel)) { - throw new Error(getErrorMessage(channel)); - } - - ipcRenderer.removeAllListeners(channel); - }, -}); diff --git a/desktop/contextBridge.ts b/desktop/contextBridge.ts new file mode 100644 index 000000000000..f2693259e51a --- /dev/null +++ b/desktop/contextBridge.ts @@ -0,0 +1,82 @@ +import {contextBridge, ipcRenderer} from 'electron'; +import ELECTRON_EVENTS from './ELECTRON_EVENTS'; + +type ContextBridgeApi = { + send: (channel: string, data?: unknown) => void; + sendSync: (channel: string, data?: unknown) => unknown; + invoke: (channel: string, ...args: unknown[]) => Promise; + on: (channel: string, func: (...args: unknown[]) => void) => void; + removeAllListeners: (channel: string) => void; +}; + +const WHITELIST_CHANNELS_RENDERER_TO_MAIN = [ + ELECTRON_EVENTS.REQUEST_DEVICE_ID, + ELECTRON_EVENTS.REQUEST_FOCUS_APP, + ELECTRON_EVENTS.REQUEST_UPDATE_BADGE_COUNT, + ELECTRON_EVENTS.REQUEST_VISIBILITY, + ELECTRON_EVENTS.START_UPDATE, + ELECTRON_EVENTS.LOCALE_UPDATED, +]; + +const WHITELIST_CHANNELS_MAIN_TO_RENDERER = [ELECTRON_EVENTS.KEYBOARD_SHORTCUTS_PAGE, ELECTRON_EVENTS.UPDATE_DOWNLOADED, ELECTRON_EVENTS.FOCUS, ELECTRON_EVENTS.BLUR]; + +const getErrorMessage = (channel: string): string => `Electron context bridge cannot be used with channel '${channel}'`; + +/** + * The following methods will be available in the renderer process under `window.electron`. + */ +contextBridge.exposeInMainWorld('electron', { + /** + * Send data asynchronously from renderer process to main process. + * Note that this is a one-way channel – main will not respond. In order to get a response from main, either: + * + * - Use `sendSync` + * - Or implement `invoke` if you want to maintain asynchronous communication: https://www.electronjs.org/docs/latest/api/ipc-renderer#ipcrendererinvokechannel-args + */ + send: (channel: string, data: unknown) => { + if (!WHITELIST_CHANNELS_RENDERER_TO_MAIN.some((whitelistChannel) => whitelistChannel === channel)) { + throw new Error(getErrorMessage(channel)); + } + + ipcRenderer.send(channel, data); + }, + + /** Send data synchronously from renderer process to main process. Main process may return a result. */ + sendSync: (channel: string, data: unknown): unknown => { + if (!WHITELIST_CHANNELS_RENDERER_TO_MAIN.some((whitelistChannel) => whitelistChannel === channel)) { + throw new Error(getErrorMessage(channel)); + } + + return ipcRenderer.sendSync(channel, data); + }, + + /** Execute a function in the main process and return a promise that resolves with its response. */ + invoke: (channel: string, ...args: unknown[]): Promise => { + if (!WHITELIST_CHANNELS_RENDERER_TO_MAIN.some((whitelistChannel) => whitelistChannel === channel)) { + throw new Error(getErrorMessage(channel)); + } + + return ipcRenderer.invoke(channel, ...args); + }, + + /** Set up a listener for events emitted from the main process and sent to the renderer process. */ + on: (channel: string, func: (...args: unknown[]) => void) => { + if (!WHITELIST_CHANNELS_MAIN_TO_RENDERER.some((whitelistChannel) => whitelistChannel === channel)) { + throw new Error(getErrorMessage(channel)); + } + + // Deliberately strip event as it includes `sender` + ipcRenderer.on(channel, (event, ...args) => func(...args)); + }, + + /** Remove listeners for a single channel from the main process and sent to the renderer process. */ + removeAllListeners: (channel: string) => { + if (!WHITELIST_CHANNELS_MAIN_TO_RENDERER.some((whitelistChannel) => whitelistChannel === channel)) { + throw new Error(getErrorMessage(channel)); + } + + ipcRenderer.removeAllListeners(channel); + }, +}); + +export default ContextBridgeApi; diff --git a/desktop/main.js b/desktop/main.ts similarity index 82% rename from desktop/main.js rename to desktop/main.ts index 4b38c5d36ab3..071ddb7c7a41 100644 --- a/desktop/main.js +++ b/desktop/main.ts @@ -1,17 +1,21 @@ -const {app, dialog, clipboard, BrowserWindow, Menu, MenuItem, shell, ipcMain} = require('electron'); -const _ = require('underscore'); -const serve = require('electron-serve'); -const contextMenu = require('electron-context-menu'); -const {autoUpdater} = require('electron-updater'); -const log = require('electron-log'); -const {machineId} = require('node-machine-id'); -const ELECTRON_EVENTS = require('./ELECTRON_EVENTS'); -const checkForUpdates = require('../src/libs/checkForUpdates'); -const CONFIG = require('../src/CONFIG').default; -const CONST = require('../src/CONST').default; -const Localize = require('../src/libs/Localize'); - -const port = process.env.PORT || 8082; +import {app, BrowserWindow, clipboard, dialog, ipcMain, Menu, MenuItem, shell} from 'electron'; +import type {BrowserView, MenuItemConstructorOptions, WebContents, WebviewTag} from 'electron'; +import contextMenu from 'electron-context-menu'; +import log from 'electron-log'; +import type {ElectronLog} from 'electron-log'; +import serve from 'electron-serve'; +import {autoUpdater} from 'electron-updater'; +import {machineId} from 'node-machine-id'; +import checkForUpdates from '@libs/checkForUpdates'; +import * as Localize from '@libs/Localize'; +import CONFIG from '@src/CONFIG'; +import CONST from '@src/CONST'; +import type {TranslationPaths} from '@src/languages/types'; +import type PlatformSpecificUpdater from '@src/setup/platformSetup/types'; +import type {Locale} from '@src/types/onyx'; +import ELECTRON_EVENTS from './ELECTRON_EVENTS'; + +const port = process.env.PORT ?? 8082; const {DESKTOP_SHORTCUT_ACCELERATOR, LOCALES} = CONST; // Setup google api key in process environment, we are setting it this way intentionally. It is required by the @@ -34,43 +38,46 @@ app.commandLine.appendSwitch('enable-network-information-downlink-max'); /** * Inserts the plain text from the clipboard into the provided browser window's web contents. * - * @param {BrowserWindow} browserWindow - The Electron BrowserWindow instance where the text should be inserted. + * @param browserWindow - The Electron BrowserWindow instance where the text should be inserted. */ -function pasteAsPlainText(browserWindow) { +function pasteAsPlainText(browserWindow: BrowserWindow | BrowserView | WebviewTag | WebContents) { const text = clipboard.readText(); - browserWindow.webContents.insertText(text); + + if ('webContents' in browserWindow) { + browserWindow.webContents.insertText(text); + } } /** * Initialize the right-click menu * See https://github.com/sindresorhus/electron-context-menu * - * @param {String} preferredLocale - The current user language to be used for translating menu labels. - * @returns {Function} A dispose function to clean up the created context menu. + * @param preferredLocale - The current user language to be used for translating menu labels. + * @returns A dispose function to clean up the created context menu. */ - -function createContextMenu(preferredLocale = LOCALES.DEFAULT) { +function createContextMenu(preferredLocale: Locale = LOCALES.DEFAULT): () => void { return contextMenu({ labels: { cut: Localize.translate(preferredLocale, 'desktopApplicationMenu.cut'), paste: Localize.translate(preferredLocale, 'desktopApplicationMenu.paste'), copy: Localize.translate(preferredLocale, 'desktopApplicationMenu.copy'), }, - append: (defaultActions, parameters, browserWindow) => [ - new MenuItem({ - // Only enable the menu item for Editable context which supports paste - visible: parameters.isEditable && parameters.editFlags.canPaste, - role: 'pasteAndMatchStyle', - accelerator: DESKTOP_SHORTCUT_ACCELERATOR.PASTE_AND_MATCH_STYLE, - label: Localize.translate(preferredLocale, 'desktopApplicationMenu.pasteAndMatchStyle'), - }), - new MenuItem({ - label: Localize.translate(preferredLocale, 'desktopApplicationMenu.pasteAsPlainText'), - visible: parameters.isEditable && parameters.editFlags.canPaste && clipboard.readText().length > 0, - accelerator: DESKTOP_SHORTCUT_ACCELERATOR.PASTE_AS_PLAIN_TEXT, - click: () => pasteAsPlainText(browserWindow), - }), - ], + append: (defaultActions, parameters, browserWindow) => + [ + new MenuItem({ + // Only enable the menu item for Editable context which supports paste + visible: parameters.isEditable && parameters.editFlags.canPaste, + role: 'pasteAndMatchStyle', + accelerator: DESKTOP_SHORTCUT_ACCELERATOR.PASTE_AND_MATCH_STYLE, + label: Localize.translate(preferredLocale, 'desktopApplicationMenu.pasteAndMatchStyle'), + }), + new MenuItem({ + label: Localize.translate(preferredLocale, 'desktopApplicationMenu.pasteAsPlainText'), + visible: parameters.isEditable && parameters.editFlags.canPaste && clipboard.readText().length > 0, + accelerator: DESKTOP_SHORTCUT_ACCELERATOR.PASTE_AS_PLAIN_TEXT, + click: () => pasteAsPlainText(browserWindow), + }), + ] as unknown as MenuItemConstructorOptions[], }); } @@ -79,11 +86,11 @@ let disposeContextMenu = createContextMenu(); // Send all autoUpdater logs to a log file: ~/Library/Logs/new.expensify.desktop/main.log // See https://www.npmjs.com/package/electron-log autoUpdater.logger = log; -autoUpdater.logger.transports.file.level = 'info'; +(autoUpdater.logger as ElectronLog).transports.file.level = 'info'; // Send all Console logs to a log file: ~/Library/Logs/new.expensify.desktop/main.log // See https://www.npmjs.com/package/electron-log -_.assign(console, log.functions); +Object.assign(console, log.functions); // This sets up the command line arguments used to manage the update. When // the --expected-update-version flag is set, the app will open pre-hidden @@ -92,23 +99,24 @@ _.assign(console, log.functions); const EXPECTED_UPDATE_VERSION_FLAG = '--expected-update-version'; const APP_DOMAIN = __DEV__ ? `https://dev.new.expensify.com:${port}` : 'app://-'; -let expectedUpdateVersion; -for (let i = 0; i < process.argv.length; i++) { - const arg = process.argv[i]; - if (arg.startsWith(`${EXPECTED_UPDATE_VERSION_FLAG}=`)) { - expectedUpdateVersion = arg.substr(`${EXPECTED_UPDATE_VERSION_FLAG}=`.length); +let expectedUpdateVersion: string; +process.argv.forEach((arg) => { + if (!arg.startsWith(`${EXPECTED_UPDATE_VERSION_FLAG}=`)) { + return; } -} + + expectedUpdateVersion = arg.substr(`${EXPECTED_UPDATE_VERSION_FLAG}=`.length); +}); // Add the listeners and variables required to ensure that auto-updating // happens correctly. let hasUpdate = false; -let downloadedVersion; +let downloadedVersion: string; // Note that we have to subscribe to this separately and cannot use Localize.translateLocal, // because the only way code can be shared between the main and renderer processes at runtime is via the context bridge // So we track preferredLocale separately via ELECTRON_EVENTS.LOCALE_UPDATED -const preferredLocale = CONST.LOCALES.DEFAULT; +const preferredLocale: Locale = CONST.LOCALES.DEFAULT; const appProtocol = CONST.DEEPLINK_BASE_URL.replace('://', ''); @@ -120,12 +128,8 @@ const quitAndInstallWithUpdate = () => { autoUpdater.quitAndInstall(); }; -/** - * Menu Item callback to triggers an update check - * @param {MenuItem} menuItem - * @param {BrowserWindow} browserWindow - */ -const manuallyCheckForUpdates = (menuItem, browserWindow) => { +/** Menu Item callback to triggers an update check */ +const manuallyCheckForUpdates = (menuItem: MenuItem, browserWindow?: BrowserWindow) => { // Disable item until the check (and download) is complete // eslint: menu item flags like enabled or visible can be dynamically toggled by mutating the object // eslint-disable-next-line no-param-reassign @@ -135,7 +139,11 @@ const manuallyCheckForUpdates = (menuItem, browserWindow) => { .checkForUpdates() .catch((error) => ({error})) .then((result) => { - const downloadPromise = result && result.downloadPromise; + const downloadPromise = result && 'downloadPromise' in result ? result.downloadPromise : undefined; + + if (!browserWindow) { + return; + } if (downloadPromise) { dialog.showMessageBox(browserWindow, { @@ -144,7 +152,7 @@ const manuallyCheckForUpdates = (menuItem, browserWindow) => { detail: Localize.translate(preferredLocale, 'checkForUpdatesModal.available.message'), buttons: [Localize.translate(preferredLocale, 'checkForUpdatesModal.available.soundsGood')], }); - } else if (result && result.error) { + } else if (result && 'error' in result && result.error) { dialog.showMessageBox(browserWindow, { type: 'error', message: Localize.translate(preferredLocale, 'checkForUpdatesModal.error.title'), @@ -170,25 +178,30 @@ const manuallyCheckForUpdates = (menuItem, browserWindow) => { }); }; -/** - * Trigger event to show keyboard shortcuts - * @param {BrowserWindow} browserWindow - */ -const showKeyboardShortcutsPage = (browserWindow) => { +/** Trigger event to show keyboard shortcuts */ +const showKeyboardShortcutsPage = (browserWindow: BrowserWindow) => { if (!browserWindow.isVisible()) { return; } browserWindow.webContents.send(ELECTRON_EVENTS.KEYBOARD_SHORTCUTS_PAGE); }; -// Actual auto-update listeners -const electronUpdater = (browserWindow) => ({ +/** Actual auto-update listeners */ +const electronUpdater = (browserWindow: BrowserWindow): PlatformSpecificUpdater => ({ init: () => { autoUpdater.on(ELECTRON_EVENTS.UPDATE_DOWNLOADED, (info) => { const systemMenu = Menu.getApplicationMenu(); + const updateMenuItem = systemMenu?.getMenuItemById(`update`); + const checkForUpdatesMenuItem = systemMenu?.getMenuItemById(`checkForUpdates`); + downloadedVersion = info.version; - systemMenu.getMenuItemById(`update`).visible = true; - systemMenu.getMenuItemById(`checkForUpdates`).visible = false; + + if (updateMenuItem) { + updateMenuItem.visible = true; + } + if (checkForUpdatesMenuItem) { + checkForUpdatesMenuItem.visible = false; + } if (browserWindow.isVisible()) { browserWindow.webContents.send(ELECTRON_EVENTS.UPDATE_DOWNLOADED, info.version); } else { @@ -204,29 +217,26 @@ const electronUpdater = (browserWindow) => ({ }, }); -/* - * @param {Menu} systemMenu - */ -const localizeMenuItems = (submenu, updatedLocale) => - _.map(submenu, (menu) => { - const newMenu = _.clone(menu); +const localizeMenuItems = (submenu: MenuItemConstructorOptions[], updatedLocale: Locale): MenuItemConstructorOptions[] => + submenu.map((menu) => { + const newMenu: MenuItemConstructorOptions = {...menu}; if (menu.id) { - const labelTranslation = Localize.translate(updatedLocale, `desktopApplicationMenu.${menu.id}`); + const labelTranslation = Localize.translate(updatedLocale, `desktopApplicationMenu.${menu.id}` as TranslationPaths); if (labelTranslation) { newMenu.label = labelTranslation; } } if (menu.submenu) { - newMenu.submenu = localizeMenuItems(menu.submenu, updatedLocale); + newMenu.submenu = localizeMenuItems(menu.submenu as MenuItemConstructorOptions[], updatedLocale); } return newMenu; }); -const mainWindow = () => { - let deeplinkUrl; - let browserWindow; +const mainWindow = (): Promise => { + let deeplinkUrl: string; + let browserWindow: BrowserWindow; - const loadURL = __DEV__ ? (win) => win.loadURL(`https://dev.new.expensify.com:${port}`) : serve({directory: `${__dirname}/www`}); + const loadURL = __DEV__ ? (win: BrowserWindow): Promise => win.loadURL(`https://dev.new.expensify.com:${port}`) : serve({directory: `${__dirname}/www`}); // Prod and staging set the icon in the electron-builder config, so only update it here for dev if (__DEV__) { @@ -296,7 +306,9 @@ const mainWindow = () => { if (!__DEV__) { // Modify the origin and referer for requests sent to our API webRequest.onBeforeSendHeaders(validDestinationFilters, (details, callback) => { + // @ts-expect-error need to confirm if it's used details.requestHeaders.origin = CONFIG.EXPENSIFY.URL_EXPENSIFY_CASH; + // @ts-expect-error need to confirm if it's used details.requestHeaders.referer = CONFIG.EXPENSIFY.URL_EXPENSIFY_CASH; callback({requestHeaders: details.requestHeaders}); }); @@ -304,9 +316,11 @@ const mainWindow = () => { // Modify access-control-allow-origin header and CSP for the response webRequest.onHeadersReceived(validDestinationFilters, (details, callback) => { - details.responseHeaders['access-control-allow-origin'] = [APP_DOMAIN]; - if (details.responseHeaders['content-security-policy']) { - details.responseHeaders['content-security-policy'] = _.map(details.responseHeaders['content-security-policy'], (value) => + if (details.responseHeaders) { + details.responseHeaders['access-control-allow-origin'] = [APP_DOMAIN]; + } + if (details.responseHeaders?.['content-security-policy']) { + details.responseHeaders['content-security-policy'] = details.responseHeaders['content-security-policy'].map((value) => value.startsWith('frame-ancestors') ? `${value} ${APP_DOMAIN}` : value, ); } @@ -319,7 +333,7 @@ const mainWindow = () => { browserWindow.setTitle('New Expensify'); } - const initialMenuTemplate = [ + const initialMenuTemplate: MenuItemConstructorOptions[] = [ { id: 'mainMenu', label: Localize.translate(preferredLocale, `desktopApplicationMenu.mainMenu`), @@ -404,6 +418,7 @@ const mainWindow = () => { submenu: [ { id: 'back', + // @ts-expect-error role doesn't exist but removing cause problems role: 'back', accelerator: process.platform === 'darwin' ? 'Cmd+[' : 'Shift+[', click: () => { @@ -411,6 +426,7 @@ const mainWindow = () => { }, }, { + // @ts-expect-error role doesn't exist but removing cause problems role: 'back', visible: false, accelerator: process.platform === 'darwin' ? 'Cmd+Left' : 'Shift+Left', @@ -420,6 +436,7 @@ const mainWindow = () => { }, { id: 'forward', + // @ts-expect-error role doesn't exist but removing cause problems role: 'forward', accelerator: process.platform === 'darwin' ? 'Cmd+]' : 'Shift+]', click: () => { @@ -427,6 +444,7 @@ const mainWindow = () => { }, }, { + // @ts-expect-error role doesn't exist but removing cause problems role: 'forward', visible: false, accelerator: process.platform === 'darwin' ? 'Cmd+Right' : 'Shift+Right', @@ -485,7 +503,7 @@ const mainWindow = () => { // When the user clicks a link that has target="_blank" (which is all external links) // open the default browser instead of a new electron window browserWindow.webContents.setWindowOpenHandler(({url}) => { - const denial = {action: 'deny'}; + const denial = {action: 'deny'} as const; // Make sure local urls stay in electron perimeter if (url.substr(0, 'file://'.length).toLowerCase() === 'file://') { diff --git a/desktop/start.js b/desktop/start.ts similarity index 88% rename from desktop/start.js rename to desktop/start.ts index 05a1b031350d..9efc7e04c9be 100644 --- a/desktop/start.js +++ b/desktop/start.ts @@ -1,7 +1,10 @@ #!/usr/bin/env node -const portfinder = require('portfinder'); +import {config} from 'dotenv'; +import portfinder from 'portfinder'; + const concurrently = require('concurrently'); -require('dotenv').config(); + +config(); const basePort = 8082; @@ -39,6 +42,8 @@ portfinder }, ]; + // concurrently lib problem + // eslint-disable-next-line @typescript-eslint/no-unsafe-return return concurrently(processes, { inputStream: process.stdin, prefix: 'name', diff --git a/package.json b/package.json index e3c23d4538d3..20a9418eb74d 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "build": "webpack --config config/webpack/webpack.common.js --env envFile=.env.production", "build-staging": "webpack --config config/webpack/webpack.common.js --env envFile=.env.staging", "build-adhoc": "webpack --config config/webpack/webpack.common.js --env envFile=.env.adhoc", - "desktop": "scripts/set-pusher-suffix.sh && ts-node desktop/start.js", + "desktop": "scripts/set-pusher-suffix.sh && ts-node desktop/start.ts", "desktop-build": "scripts/build-desktop.sh production", "desktop-build-staging": "scripts/build-desktop.sh staging", "createDocsRoutes": "ts-node .github/scripts/createDocsRoutes.js", diff --git a/src/types/modules/electron.d.ts b/src/types/modules/electron.d.ts index 09e33f29ba38..7b2ecaa3866d 100644 --- a/src/types/modules/electron.d.ts +++ b/src/types/modules/electron.d.ts @@ -1,11 +1,4 @@ -// TODO: Move this type to desktop/contextBridge.js once it is converted to TS -type ContextBridgeApi = { - send: (channel: string, data?: unknown) => void; - sendSync: (channel: string, data?: unknown) => unknown; - invoke: (channel: string, ...args: unknown) => Promise; - on: (channel: string, func: () => void) => void; - removeAllListeners: (channel: string) => void; -}; +import type ContextBridgeApi from '@desktop/contextBridge'; declare global { // eslint-disable-next-line @typescript-eslint/consistent-type-definitions From 46d1bf52143d4647dd74737e05cc819b044c7980 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Mon, 4 Mar 2024 14:25:29 +0100 Subject: [PATCH 2/6] Improve typing --- desktop/main.ts | 49 +++++++++++++++++++----------------------------- desktop/start.ts | 4 +--- 2 files changed, 20 insertions(+), 33 deletions(-) diff --git a/desktop/main.ts b/desktop/main.ts index 071ddb7c7a41..cbc12d9d2608 100644 --- a/desktop/main.ts +++ b/desktop/main.ts @@ -1,5 +1,5 @@ -import {app, BrowserWindow, clipboard, dialog, ipcMain, Menu, MenuItem, shell} from 'electron'; -import type {BrowserView, MenuItemConstructorOptions, WebContents, WebviewTag} from 'electron'; +import {app, BrowserWindow, clipboard, dialog, ipcMain, Menu, shell} from 'electron'; +import type {BrowserView, MenuItem, MenuItemConstructorOptions, WebContents, WebviewTag} from 'electron'; import contextMenu from 'electron-context-menu'; import log from 'electron-log'; import type {ElectronLog} from 'electron-log'; @@ -62,22 +62,21 @@ function createContextMenu(preferredLocale: Locale = LOCALES.DEFAULT): () => voi paste: Localize.translate(preferredLocale, 'desktopApplicationMenu.paste'), copy: Localize.translate(preferredLocale, 'desktopApplicationMenu.copy'), }, - append: (defaultActions, parameters, browserWindow) => - [ - new MenuItem({ - // Only enable the menu item for Editable context which supports paste - visible: parameters.isEditable && parameters.editFlags.canPaste, - role: 'pasteAndMatchStyle', - accelerator: DESKTOP_SHORTCUT_ACCELERATOR.PASTE_AND_MATCH_STYLE, - label: Localize.translate(preferredLocale, 'desktopApplicationMenu.pasteAndMatchStyle'), - }), - new MenuItem({ - label: Localize.translate(preferredLocale, 'desktopApplicationMenu.pasteAsPlainText'), - visible: parameters.isEditable && parameters.editFlags.canPaste && clipboard.readText().length > 0, - accelerator: DESKTOP_SHORTCUT_ACCELERATOR.PASTE_AS_PLAIN_TEXT, - click: () => pasteAsPlainText(browserWindow), - }), - ] as unknown as MenuItemConstructorOptions[], + append: (defaultActions, parameters, browserWindow) => [ + { + // Only enable the menu item for Editable context which supports paste + visible: parameters.isEditable && parameters.editFlags.canPaste, + role: 'pasteAndMatchStyle', + accelerator: DESKTOP_SHORTCUT_ACCELERATOR.PASTE_AND_MATCH_STYLE, + label: Localize.translate(preferredLocale, 'desktopApplicationMenu.pasteAndMatchStyle'), + }, + { + label: Localize.translate(preferredLocale, 'desktopApplicationMenu.pasteAsPlainText'), + visible: parameters.isEditable && parameters.editFlags.canPaste && clipboard.readText().length > 0, + accelerator: DESKTOP_SHORTCUT_ACCELERATOR.PASTE_AS_PLAIN_TEXT, + click: () => pasteAsPlainText(browserWindow), + }, + ], }); } @@ -306,10 +305,6 @@ const mainWindow = (): Promise => { if (!__DEV__) { // Modify the origin and referer for requests sent to our API webRequest.onBeforeSendHeaders(validDestinationFilters, (details, callback) => { - // @ts-expect-error need to confirm if it's used - details.requestHeaders.origin = CONFIG.EXPENSIFY.URL_EXPENSIFY_CASH; - // @ts-expect-error need to confirm if it's used - details.requestHeaders.referer = CONFIG.EXPENSIFY.URL_EXPENSIFY_CASH; callback({requestHeaders: details.requestHeaders}); }); } @@ -418,16 +413,13 @@ const mainWindow = (): Promise => { submenu: [ { id: 'back', - // @ts-expect-error role doesn't exist but removing cause problems - role: 'back', accelerator: process.platform === 'darwin' ? 'Cmd+[' : 'Shift+[', click: () => { browserWindow.webContents.goBack(); }, }, { - // @ts-expect-error role doesn't exist but removing cause problems - role: 'back', + label: 'backWithKeyShortcut', visible: false, accelerator: process.platform === 'darwin' ? 'Cmd+Left' : 'Shift+Left', click: () => { @@ -436,16 +428,13 @@ const mainWindow = (): Promise => { }, { id: 'forward', - // @ts-expect-error role doesn't exist but removing cause problems - role: 'forward', accelerator: process.platform === 'darwin' ? 'Cmd+]' : 'Shift+]', click: () => { browserWindow.webContents.goForward(); }, }, { - // @ts-expect-error role doesn't exist but removing cause problems - role: 'forward', + label: 'forwardWithKeyShortcut', visible: false, accelerator: process.platform === 'darwin' ? 'Cmd+Right' : 'Shift+Right', click: () => { diff --git a/desktop/start.ts b/desktop/start.ts index 9efc7e04c9be..f92cd10dc5aa 100644 --- a/desktop/start.ts +++ b/desktop/start.ts @@ -42,8 +42,6 @@ portfinder }, ]; - // concurrently lib problem - // eslint-disable-next-line @typescript-eslint/no-unsafe-return return concurrently(processes, { inputStream: process.stdin, prefix: 'name', @@ -53,6 +51,6 @@ portfinder }).then( () => process.exit(0), () => process.exit(1), - ); + ) as never; }) .catch(() => process.exit(1)); From 9f7258c4c6ec7a127be94b704de6d7b95cada235 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Mon, 4 Mar 2024 15:50:28 +0100 Subject: [PATCH 3/6] Re-run checks From ab1369805213034680390bd4d572b50047972612 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Tue, 5 Mar 2024 11:56:42 +0100 Subject: [PATCH 4/6] Update concurrently lib, minor code improvements --- desktop/contextBridge.ts | 4 +- desktop/start.ts | 17 +- package-lock.json | 621 +++++++++------------------------------ package.json | 2 +- 4 files changed, 145 insertions(+), 499 deletions(-) diff --git a/desktop/contextBridge.ts b/desktop/contextBridge.ts index f2693259e51a..689c69de0cc8 100644 --- a/desktop/contextBridge.ts +++ b/desktop/contextBridge.ts @@ -16,9 +16,9 @@ const WHITELIST_CHANNELS_RENDERER_TO_MAIN = [ ELECTRON_EVENTS.REQUEST_VISIBILITY, ELECTRON_EVENTS.START_UPDATE, ELECTRON_EVENTS.LOCALE_UPDATED, -]; +] as const; -const WHITELIST_CHANNELS_MAIN_TO_RENDERER = [ELECTRON_EVENTS.KEYBOARD_SHORTCUTS_PAGE, ELECTRON_EVENTS.UPDATE_DOWNLOADED, ELECTRON_EVENTS.FOCUS, ELECTRON_EVENTS.BLUR]; +const WHITELIST_CHANNELS_MAIN_TO_RENDERER = [ELECTRON_EVENTS.KEYBOARD_SHORTCUTS_PAGE, ELECTRON_EVENTS.UPDATE_DOWNLOADED, ELECTRON_EVENTS.FOCUS, ELECTRON_EVENTS.BLUR] as const; const getErrorMessage = (channel: string): string => `Electron context bridge cannot be used with channel '${channel}'`; diff --git a/desktop/start.ts b/desktop/start.ts index f92cd10dc5aa..17ec690507ed 100644 --- a/desktop/start.ts +++ b/desktop/start.ts @@ -1,10 +1,9 @@ #!/usr/bin/env node -import {config} from 'dotenv'; +import concurrently from 'concurrently'; +import {config as configDotenv} from 'dotenv'; import portfinder from 'portfinder'; -const concurrently = require('concurrently'); - -config(); +configDotenv(); const basePort = 8082; @@ -12,7 +11,7 @@ portfinder .getPortPromise({ port: basePort, }) - .then((port) => { + .then((port): Promise => { const devServer = `webpack-dev-server --config config/webpack/webpack.dev.js --port ${port} --env platform=desktop`; const buildMain = 'webpack watch --config config/webpack/webpack.desktop.js --config-name desktop-main --mode=development'; @@ -42,15 +41,17 @@ portfinder }, ]; - return concurrently(processes, { + const {result} = concurrently(processes, { inputStream: process.stdin, prefix: 'name', // Like Harry Potter and he-who-must-not-be-named, "neither can live while the other survives" killOthers: ['success', 'failure'], - }).then( + }); + + return result.then( () => process.exit(0), () => process.exit(1), - ) as never; + ); }) .catch(() => process.exit(1)); diff --git a/package-lock.json b/package-lock.json index 80d3d1c6e911..db601a4ac37b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -197,7 +197,7 @@ "babel-plugin-transform-class-properties": "^6.24.1", "babel-plugin-transform-remove-console": "^6.9.4", "clean-webpack-plugin": "^3.0.0", - "concurrently": "^5.3.0", + "concurrently": "^8.2.2", "copy-webpack-plugin": "^6.4.1", "css-loader": "^6.7.2", "diff-so-fancy": "^1.3.0", @@ -2709,20 +2709,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@callstack/reassure-cli/node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/@callstack/reassure-cli/node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -2762,42 +2748,6 @@ "node": ">=8" } }, - "node_modules/@callstack/reassure-cli/node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@callstack/reassure-cli/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@callstack/reassure-cli/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, "node_modules/@callstack/reassure-compare": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/@callstack/reassure-compare/-/reassure-compare-0.6.0.tgz", @@ -26041,75 +25991,16 @@ } }, "node_modules/cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true, - "license": "MIT" - }, - "node_modules/cliui/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/cliui/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "license": "MIT", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">=6" + "node": ">=12" } }, "node_modules/clone": { @@ -26457,40 +26348,115 @@ } }, "node_modules/concurrently": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-5.3.0.tgz", - "integrity": "sha512-8MhqOB6PWlBfA2vJ8a0bSFKATOdWlHiQlk11IfmQBPaHVP8oP2gsh2MObE6UR3hqDHqvaIvLTyceNW6obVuFHQ==", + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-8.2.2.tgz", + "integrity": "sha512-1dP4gpXFhei8IOtlXRE/T/4H88ElHgTiUzh71YUmtjTEHMSRS2Z/fgOxHSxxusGHogsRfxNq1vyAwxSC+EVyDg==", "dev": true, - "license": "MIT", "dependencies": { - "chalk": "^2.4.2", - "date-fns": "^2.0.1", - "lodash": "^4.17.15", - "read-pkg": "^4.0.1", - "rxjs": "^6.5.2", - "spawn-command": "^0.0.2-1", - "supports-color": "^6.1.0", + "chalk": "^4.1.2", + "date-fns": "^2.30.0", + "lodash": "^4.17.21", + "rxjs": "^7.8.1", + "shell-quote": "^1.8.1", + "spawn-command": "0.0.2", + "supports-color": "^8.1.1", "tree-kill": "^1.2.2", - "yargs": "^13.3.0" + "yargs": "^17.7.2" }, "bin": { - "concurrently": "bin/concurrently.js" + "conc": "dist/bin/concurrently.js", + "concurrently": "dist/bin/concurrently.js" }, "engines": { - "node": ">=6.0.0" + "node": "^14.13.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/concurrently/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/concurrently/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/concurrently/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" } }, "node_modules/concurrently/node_modules/supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, - "license": "MIT", "dependencies": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, "node_modules/config-file-ts": { @@ -28722,20 +28688,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/electron-builder/node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/electron-builder/node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -28794,42 +28746,6 @@ "node": ">=8" } }, - "node_modules/electron-builder/node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/electron-builder/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/electron-builder/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, "node_modules/electron-publish": { "version": "24.5.0", "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-24.5.0.tgz", @@ -35634,20 +35550,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-cli/node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/jest-cli/node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -35687,41 +35589,6 @@ "node": ">=8" } }, - "node_modules/jest-cli/node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/jest-cli/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/jest-cli/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, "node_modules/jest-config": { "version": "29.4.1", "license": "MIT", @@ -39736,16 +39603,6 @@ "tslib": "2" } }, - "node_modules/memfs/node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dev": true, - "peer": true, - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/memoize-one": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", @@ -40462,19 +40319,6 @@ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" }, - "node_modules/metro/node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/metro/node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -40600,39 +40444,6 @@ } } }, - "node_modules/metro/node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "engines": { - "node": ">=10" - } - }, - "node_modules/metro/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/metro/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "engines": { - "node": ">=12" - } - }, "node_modules/microevent.ts": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/microevent.ts/-/microevent.ts-0.1.1.tgz", @@ -44871,19 +44682,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/react-native/node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/react-native/node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -44975,39 +44773,6 @@ "async-limiter": "~1.0.0" } }, - "node_modules/react-native/node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "engines": { - "node": ">=10" - } - }, - "node_modules/react-native/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/react-native/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "engines": { - "node": ">=12" - } - }, "node_modules/react-pdf": { "version": "7.3.3", "resolved": "https://registry.npmjs.org/react-pdf/-/react-pdf-7.3.3.tgz", @@ -46791,25 +46556,14 @@ "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" }, "node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", "dev": true, - "license": "Apache-2.0", "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" + "tslib": "^2.1.0" } }, - "node_modules/rxjs/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true, - "license": "0BSD" - }, "node_modules/safe-array-concat": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz", @@ -48008,11 +47762,10 @@ } }, "node_modules/spawn-command": { - "version": "0.0.2-1", - "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", - "integrity": "sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==", - "dev": true, - "license": "MIT" + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2.tgz", + "integrity": "sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==", + "dev": true }, "node_modules/spdx-correct": { "version": "3.1.1", @@ -52692,22 +52445,20 @@ } }, "node_modules/yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "license": "MIT", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" } }, "node_modules/yargs-parser": { @@ -52720,126 +52471,20 @@ "node": ">=10" } }, - "node_modules/yargs/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true, - "license": "MIT" - }, - "node_modules/yargs/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/yargs/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yargs/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^4.1.0" - }, + "node_modules/yargs/node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "engines": { - "node": ">=6" + "node": ">=10" } }, "node_modules/yargs/node_modules/yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "license": "ISC", - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" } }, "node_modules/yauzl": { diff --git a/package.json b/package.json index 92afaafc85e7..7f5847d50608 100644 --- a/package.json +++ b/package.json @@ -246,7 +246,7 @@ "babel-plugin-transform-class-properties": "^6.24.1", "babel-plugin-transform-remove-console": "^6.9.4", "clean-webpack-plugin": "^3.0.0", - "concurrently": "^5.3.0", + "concurrently": "^8.2.2", "copy-webpack-plugin": "^6.4.1", "css-loader": "^6.7.2", "diff-so-fancy": "^1.3.0", From bb932cbed6602f6c6c527e504d0a67e0a429e761 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Tue, 5 Mar 2024 12:08:19 +0100 Subject: [PATCH 5/6] Update files extension in the README --- desktop/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/desktop/README.md b/desktop/README.md index 4493196b5ed4..2fc074153d87 100644 --- a/desktop/README.md +++ b/desktop/README.md @@ -37,9 +37,9 @@ The desktop app is organized in three pieces: - This is the webpack-bundled version of our react-native-web app (except using `index.desktop.js` files instead of `index.website.js`, where applicable) - This is _very_ similar to our web app, and code in this process should assume it will be run in the context of a browser (no access to `require`, Electron, or Node.js APis) 3. The context bridge - - Implemented in https://github.com/Expensify/App/blob/main/desktop/contextBridge.js + - Implemented in https://github.com/Expensify/App/blob/main/desktop/contextBridge.ts - The context bridge enables communication between the main and renderer processes. For example, if the renderer process needs to make use of a Node.js or Electron API it must: - 1. Define an event in https://github.com/Expensify/App/blob/main/desktop/ELECTRON_EVENTS.js + 1. Define an event in https://github.com/Expensify/App/blob/main/desktop/ELECTRON_EVENTS.ts 2. Add that event to the whitelist defined in the context bridge 3. Set up a handler for the event in the main process that can respond to the renderer process back through the bridge, if necessary. From ec0efd09d5e6f659cb2eca1c3887995197d95bc1 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Fri, 15 Mar 2024 19:29:20 +0100 Subject: [PATCH 6/6] Re-run npm install --- package-lock.json | 553 +++++++++++----------------------------------- 1 file changed, 133 insertions(+), 420 deletions(-) diff --git a/package-lock.json b/package-lock.json index d67a015a563b..a84a72dd5167 100644 --- a/package-lock.json +++ b/package-lock.json @@ -199,7 +199,7 @@ "babel-plugin-transform-class-properties": "^6.24.1", "babel-plugin-transform-remove-console": "^6.9.4", "clean-webpack-plugin": "^3.0.0", - "concurrently": "^5.3.0", + "concurrently": "^8.2.2", "copy-webpack-plugin": "^6.4.1", "css-loader": "^6.7.2", "diff-so-fancy": "^1.3.0", @@ -2514,19 +2514,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@callstack/reassure-cli/node_modules/cliui": { - "version": "8.0.1", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/@callstack/reassure-cli/node_modules/color-convert": { "version": "2.0.1", "dev": true, @@ -2562,39 +2549,6 @@ "node": ">=8" } }, - "node_modules/@callstack/reassure-cli/node_modules/y18n": { - "version": "5.0.8", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/@callstack/reassure-cli/node_modules/yargs": { - "version": "17.7.2", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@callstack/reassure-cli/node_modules/yargs-parser": { - "version": "21.1.1", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, "node_modules/@callstack/reassure-compare": { "version": "0.6.0", "dev": true, @@ -23136,63 +23090,16 @@ } }, "node_modules/cliui": { - "version": "5.0.0", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "7.0.3", - "dev": true, - "license": "MIT" - }, - "node_modules/cliui/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/cliui/node_modules/string-width": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "5.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "5.1.0", - "dev": true, - "license": "MIT", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">=6" + "node": ">=12" } }, "node_modules/clone": { @@ -23510,36 +23417,115 @@ } }, "node_modules/concurrently": { - "version": "5.3.0", + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-8.2.2.tgz", + "integrity": "sha512-1dP4gpXFhei8IOtlXRE/T/4H88ElHgTiUzh71YUmtjTEHMSRS2Z/fgOxHSxxusGHogsRfxNq1vyAwxSC+EVyDg==", "dev": true, - "license": "MIT", "dependencies": { - "chalk": "^2.4.2", - "date-fns": "^2.0.1", - "lodash": "^4.17.15", - "read-pkg": "^4.0.1", - "rxjs": "^6.5.2", - "spawn-command": "^0.0.2-1", - "supports-color": "^6.1.0", + "chalk": "^4.1.2", + "date-fns": "^2.30.0", + "lodash": "^4.17.21", + "rxjs": "^7.8.1", + "shell-quote": "^1.8.1", + "spawn-command": "0.0.2", + "supports-color": "^8.1.1", "tree-kill": "^1.2.2", - "yargs": "^13.3.0" + "yargs": "^17.7.2" }, "bin": { - "concurrently": "bin/concurrently.js" + "conc": "dist/bin/concurrently.js", + "concurrently": "dist/bin/concurrently.js" }, "engines": { - "node": ">=6.0.0" + "node": "^14.13.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/concurrently/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/concurrently/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/concurrently/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" } }, "node_modules/concurrently/node_modules/supports-color": { - "version": "6.1.0", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, - "license": "MIT", "dependencies": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, "node_modules/config-file-ts": { @@ -25593,19 +25579,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/electron-builder/node_modules/cliui": { - "version": "8.0.1", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/electron-builder/node_modules/color-convert": { "version": "2.0.1", "dev": true, @@ -25654,39 +25627,6 @@ "node": ">=8" } }, - "node_modules/electron-builder/node_modules/y18n": { - "version": "5.0.8", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/electron-builder/node_modules/yargs": { - "version": "17.7.2", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/electron-builder/node_modules/yargs-parser": { - "version": "21.1.1", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, "node_modules/electron-publish": { "version": "24.13.1", "dev": true, @@ -31601,18 +31541,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-cli/node_modules/cliui": { - "version": "8.0.1", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/jest-cli/node_modules/color-convert": { "version": "2.0.1", "license": "MIT", @@ -31644,36 +31572,6 @@ "node": ">=8" } }, - "node_modules/jest-cli/node_modules/y18n": { - "version": "5.0.8", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/jest-cli/node_modules/yargs": { - "version": "17.7.2", - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/jest-cli/node_modules/yargs-parser": { - "version": "21.1.1", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, "node_modules/jest-config": { "version": "29.4.1", "license": "MIT", @@ -35252,15 +35150,6 @@ "tslib": "2" } }, - "node_modules/memfs/node_modules/rxjs": { - "version": "7.8.1", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/memoize-one": { "version": "5.2.1", "license": "MIT" @@ -35907,18 +35796,6 @@ "version": "2.0.0", "license": "MIT" }, - "node_modules/metro/node_modules/cliui": { - "version": "8.0.1", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/metro/node_modules/color-convert": { "version": "2.0.1", "license": "MIT", @@ -36031,36 +35908,6 @@ } } }, - "node_modules/metro/node_modules/y18n": { - "version": "5.0.8", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/metro/node_modules/yargs": { - "version": "17.7.2", - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/metro/node_modules/yargs-parser": { - "version": "21.1.1", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, "node_modules/microevent.ts": { "version": "0.1.1", "dev": true, @@ -39709,18 +39556,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/react-native/node_modules/cliui": { - "version": "8.0.1", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/react-native/node_modules/color-convert": { "version": "2.0.1", "license": "MIT", @@ -39802,36 +39637,6 @@ "async-limiter": "~1.0.0" } }, - "node_modules/react-native/node_modules/y18n": { - "version": "5.0.8", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/react-native/node_modules/yargs": { - "version": "17.7.2", - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/react-native/node_modules/yargs-parser": { - "version": "21.1.1", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, "node_modules/react-pdf": { "version": "7.3.3", "license": "MIT", @@ -41389,21 +41194,14 @@ "license": "BSD-3-Clause" }, "node_modules/rxjs": { - "version": "6.6.7", + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", "dev": true, - "license": "Apache-2.0", "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" + "tslib": "^2.1.0" } }, - "node_modules/rxjs/node_modules/tslib": { - "version": "1.14.1", - "dev": true, - "license": "0BSD" - }, "node_modules/safe-array-concat": { "version": "1.0.0", "dev": true, @@ -42341,9 +42139,10 @@ } }, "node_modules/spawn-command": { - "version": "0.0.2-1", - "dev": true, - "license": "MIT" + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2.tgz", + "integrity": "sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==", + "dev": true }, "node_modules/spdx-correct": { "version": "3.1.1", @@ -46384,20 +46183,20 @@ } }, "node_modules/yargs": { - "version": "13.3.2", - "dev": true, - "license": "MIT", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" } }, "node_modules/yargs-parser": { @@ -46408,106 +46207,20 @@ "node": ">=10" } }, - "node_modules/yargs/node_modules/camelcase": { - "version": "5.3.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "7.0.3", - "dev": true, - "license": "MIT" - }, - "node_modules/yargs/node_modules/find-up": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/yargs/node_modules/locate-path": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/p-limit": { - "version": "2.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yargs/node_modules/p-locate": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/string-width": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "5.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^4.1.0" - }, + "node_modules/yargs/node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "engines": { - "node": ">=6" + "node": ">=10" } }, "node_modules/yargs/node_modules/yargs-parser": { - "version": "13.1.2", - "dev": true, - "license": "ISC", - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" } }, "node_modules/yauzl": {