From fbb3ba9b164eae56680c2d0c1e00bd32de1ca9cb Mon Sep 17 00:00:00 2001 From: Ira Hopkinson Date: Mon, 13 Mar 2023 16:52:11 +1300 Subject: [PATCH] Fix lint errors --- .eslintrc.js | 14 +++- package-lock.json | 4 +- package.json | 4 +- .../services/ExtensionService.ts | 24 +++---- src/main/main.ts | 13 ++-- src/renderer/components/docking/ErrorTab.tsx | 4 +- .../components/docking/ParanextDockLayout.tsx | 4 +- .../components/docking/ParanextPanel.tsx | 4 +- .../components/docking/ParanextTabTitle.tsx | 4 +- src/renderer/testing/HelloPanel.tsx | 4 +- src/renderer/testing/TestButtonsPanel.tsx | 8 ++- src/renderer/testing/TestPanel.tsx | 4 +- src/shared/globalThis.ts | 17 +++-- src/shared/services/NetworkService.ts | 72 +++++++++---------- src/shared/util/PapiUtil.ts | 2 +- src/shared/util/Util.ts | 1 + 16 files changed, 97 insertions(+), 86 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index e7085945cb..665bf426aa 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -15,8 +15,14 @@ module.exports = { // #region Our rules - // This is already a Typescript rule, so we don't need it to be reported twice - '@typescript-eslint/no-unused-vars': 'off', + '@typescript-eslint/no-explicit-any': 'error', + '@typescript-eslint/no-non-null-assertion': 'error', + 'no-redeclare': 'off', + '@typescript-eslint/no-redeclare': 'error', + 'no-shadow': 'off', + '@typescript-eslint/no-shadow': 'error', + 'no-unused-vars': 'off', + '@typescript-eslint/no-unused-vars': 'error', 'comma-dangle': ['error', 'always-multiline'], indent: 'off', 'jsx-a11y/label-has-associated-control': [ @@ -35,6 +41,9 @@ module.exports = { // #endregion }, + globals: { + globalThis: 'readonly', + }, parserOptions: { ecmaVersion: 2020, sourceType: 'module', @@ -42,6 +51,7 @@ module.exports = { tsconfigRootDir: __dirname, createDefaultProgram: true, }, + plugins: ['@typescript-eslint'], settings: { 'import/resolver': { // See https://github.com/benmosher/eslint-plugin-import/issues/1396#issuecomment-575727774 for line below diff --git a/package-lock.json b/package-lock.json index f17c0f65fa..c5afcffa5e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,8 +37,8 @@ "@types/terser-webpack-plugin": "^5.0.4", "@types/webpack-bundle-analyzer": "^4.6.0", "@types/ws": "^8.5.4", - "@typescript-eslint/eslint-plugin": "^5.51.0", - "@typescript-eslint/parser": "^5.51.0", + "@typescript-eslint/eslint-plugin": "^5.54.1", + "@typescript-eslint/parser": "^5.54.1", "browserslist-config-erb": "^0.0.3", "chalk": "^4.1.2", "concurrently": "^7.6.0", diff --git a/package.json b/package.json index 0d686a7001..410debe803 100644 --- a/package.json +++ b/package.json @@ -110,8 +110,8 @@ "@types/terser-webpack-plugin": "^5.0.4", "@types/webpack-bundle-analyzer": "^4.6.0", "@types/ws": "^8.5.4", - "@typescript-eslint/eslint-plugin": "^5.51.0", - "@typescript-eslint/parser": "^5.51.0", + "@typescript-eslint/eslint-plugin": "^5.54.1", + "@typescript-eslint/parser": "^5.54.1", "browserslist-config-erb": "^0.0.3", "chalk": "^4.1.2", "concurrently": "^7.6.0", diff --git a/src/extension-host/services/ExtensionService.ts b/src/extension-host/services/ExtensionService.ts index 026964ad43..fee17a2fe7 100644 --- a/src/extension-host/services/ExtensionService.ts +++ b/src/extension-host/services/ExtensionService.ts @@ -15,18 +15,6 @@ import Module from 'module'; import papi from '@shared/services/papi'; import logger from '@shared/util/logger'; -/** Whether this service has finished setting up */ -let isInitialized = false; - -/** Promise that resolves when this service is finished initializing */ -let initializePromise: Promise | undefined; - -/** Extensions that are available to us */ -let availableExtensions: ExtensionInfo[]; - -/** Map of extension name to extension that is currently active and running */ -const activeExtensions = new Map(); - /** Information about an extension provided by the extension developer */ type ExtensionManifest = Readonly<{ name: string; @@ -48,6 +36,18 @@ type ActiveExtension = { deactivator: UnsubscriberAsync; }; +/** Whether this service has finished setting up */ +let isInitialized = false; + +/** Promise that resolves when this service is finished initializing */ +let initializePromise: Promise | undefined; + +/** Extensions that are available to us */ +let availableExtensions: ExtensionInfo[]; + +/** Map of extension name to extension that is currently active and running */ +const activeExtensions = new Map(); + /** Get information for all the extensions present */ const getExtensions = async (): Promise => { const extensionFolders = (await readDir('resources://extensions'))[ diff --git a/src/main/main.ts b/src/main/main.ts index 547091e0b7..8cb3cf5d7b 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -7,7 +7,13 @@ * `./src/main.js` using webpack. This gives us some performance wins. */ import path from 'path'; -import { app, BrowserWindow, shell, ipcMain } from 'electron'; +import { + app, + BrowserWindow, + shell, + ipcMain, + IpcMainInvokeEvent, +} from 'electron'; import { autoUpdater } from 'electron-updater'; import windowStateKeeper from 'electron-window-state'; import '@main/globalThis'; @@ -154,7 +160,7 @@ app.on('will-quit', () => { /** Map from ipc channel to handler function. Use with ipcRenderer.invoke */ const ipcHandlers: { [ipcChannel: string]: ( - event: Electron.IpcMainInvokeEvent, + event: IpcMainInvokeEvent, // We don't know the exact parameter types since ipc handlers can be anything // eslint-disable-next-line @typescript-eslint/no-explicit-any ...args: any[] @@ -215,8 +221,7 @@ const commandHandlers: { [commandName: string]: CommandHandler } = { Object.entries(ipcHandlers).forEach(([ipcHandle, handler]) => { NetworkService.registerRequestHandler( ipcHandle, - async (...args: unknown[]) => - handler({} as Electron.IpcMainInvokeEvent, ...args), + async (...args: unknown[]) => handler({} as IpcMainInvokeEvent, ...args), ); }); Object.entries(commandHandlers).forEach(([commandName, handler]) => { diff --git a/src/renderer/components/docking/ErrorTab.tsx b/src/renderer/components/docking/ErrorTab.tsx index c37983d957..ab9477e809 100644 --- a/src/renderer/components/docking/ErrorTab.tsx +++ b/src/renderer/components/docking/ErrorTab.tsx @@ -1,6 +1,6 @@ import { TabInfo } from '@shared/data/WebviewTypes'; -const ErrorTab = ({ errorMessage }: { errorMessage: string }) => { +function ErrorTab({ errorMessage }: { errorMessage: string }) { return ( <>
@@ -10,7 +10,7 @@ const ErrorTab = ({ errorMessage }: { errorMessage: string }) => {
Message: {errorMessage}
); -}; +} /** * Creates a new error message tab with the specified error message diff --git a/src/renderer/components/docking/ParanextDockLayout.tsx b/src/renderer/components/docking/ParanextDockLayout.tsx index 3480d6b518..9ea95ee122 100644 --- a/src/renderer/components/docking/ParanextDockLayout.tsx +++ b/src/renderer/components/docking/ParanextDockLayout.tsx @@ -76,7 +76,7 @@ const groups: { }, }; -const ParanextDockLayout = () => { +function ParanextDockLayout() { return ( { style={{ position: 'absolute', left: 3, top: 3, right: 3, bottom: 3 }} /> ); -}; +} export default ParanextDockLayout; diff --git a/src/renderer/components/docking/ParanextPanel.tsx b/src/renderer/components/docking/ParanextPanel.tsx index 9cad7ac47e..2a098ed893 100644 --- a/src/renderer/components/docking/ParanextPanel.tsx +++ b/src/renderer/components/docking/ParanextPanel.tsx @@ -5,8 +5,8 @@ import './ParanextPanel.css'; * Used for possible styling on every panel in Paranext * @param children The children of the panel (usually supplied from an extension) */ -const ParanextPanel = ({ children }: { children: ReactNode }) => { +function ParanextPanel({ children }: { children: ReactNode }) { return
{children}
; -}; +} export default ParanextPanel; diff --git a/src/renderer/components/docking/ParanextTabTitle.tsx b/src/renderer/components/docking/ParanextTabTitle.tsx index 4d4407fa1c..2772d7aa75 100644 --- a/src/renderer/components/docking/ParanextTabTitle.tsx +++ b/src/renderer/components/docking/ParanextTabTitle.tsx @@ -5,7 +5,7 @@ import logger from '@shared/util/logger'; * Custom tab title for all tabs in Paranext * @param text The text to show on the tab title */ -const ParanextTabTitle = ({ text }: { text: string }) => { +function ParanextTabTitle({ text }: { text: string }) { const toggleDropdown = () => { logger.log('Pretend a menu was shown!'); }; @@ -21,6 +21,6 @@ const ParanextTabTitle = ({ text }: { text: string }) => { {text}
); -}; +} export default ParanextTabTitle; diff --git a/src/renderer/testing/HelloPanel.tsx b/src/renderer/testing/HelloPanel.tsx index 812b162e18..a7eaf75f47 100644 --- a/src/renderer/testing/HelloPanel.tsx +++ b/src/renderer/testing/HelloPanel.tsx @@ -1,7 +1,7 @@ import icon from '@assets/icon.png'; import { TabInfo } from '@shared/data/WebviewTypes'; -const HelloPanel = () => { +function HelloPanel() { return (
{
); -}; +} const createHelloPanel = (): TabInfo => { return { diff --git a/src/renderer/testing/TestButtonsPanel.tsx b/src/renderer/testing/TestButtonsPanel.tsx index 8a60147da0..600fdbc097 100644 --- a/src/renderer/testing/TestButtonsPanel.tsx +++ b/src/renderer/testing/TestButtonsPanel.tsx @@ -110,7 +110,7 @@ const executeMany = async (fn: () => Promise) => { } }; -const TestButtonsPanel = () => { +function TestButtonsPanel() { const [promiseReturn, setPromiseReturn] = useState('Click a button.'); const updatePromiseReturn = useCallback( (state: unknown) => @@ -122,7 +122,9 @@ const TestButtonsPanel = () => { const [resourcesPath] = usePromise( useCallback(async () => { - await new Promise((resolve) => setTimeout(() => resolve(), 5000)); + await new Promise((resolve) => { + setTimeout(() => resolve(), 5000); + }); return getResourcesPath(); }, []), 'retrieving', @@ -379,7 +381,7 @@ const TestButtonsPanel = () => { ))} ); -}; +} const createButtonsPanel = (): TabInfo => { return { diff --git a/src/renderer/testing/TestPanel.tsx b/src/renderer/testing/TestPanel.tsx index 69fda0eeef..9f9dac47cb 100644 --- a/src/renderer/testing/TestPanel.tsx +++ b/src/renderer/testing/TestPanel.tsx @@ -5,9 +5,9 @@ export type TabData = { content: string; }; -const TestPanel = ({ content }: { content: string }) => { +function TestPanel({ content }: { content: string }) { return
{content}
; -}; +} const createTabPanel = (tabInfo: SavedTabInfo): TabInfo => { if (!tabInfo.data) throw Error('Tab creation data is missing'); diff --git a/src/shared/globalThis.ts b/src/shared/globalThis.ts index 3a076a74bc..d062174d68 100644 --- a/src/shared/globalThis.ts +++ b/src/shared/globalThis.ts @@ -1,10 +1,17 @@ /* eslint-disable vars-on-top */ /* eslint-disable no-var */ +/** Type of Paranext process */ +// eslint-disable-next-line import/prefer-default-export +export enum ProcessType { + Main = 'main', + Renderer = 'renderer', + ExtensionHost = 'extension-host', +} + /** * Variables that are defined in global scope. These must be defined in main.ts (main), index.ts (renderer), and extension-host.ts (extension host) */ - declare global { /** Type of process this is. Helps with running specific code based on which process you're in */ var processType: ProcessType; @@ -13,11 +20,3 @@ declare global { /** Path to the app's resources directory. This is a string representation of the resources uri on frontend */ var resourcesPath: string; } - -/** Type of Paranext process */ -// eslint-disable-next-line import/prefer-default-export -export enum ProcessType { - Main = 'main', - Renderer = 'renderer', - ExtensionHost = 'extension-host', -} diff --git a/src/shared/services/NetworkService.ts b/src/shared/services/NetworkService.ts index 359e040a2c..452b3c5528 100644 --- a/src/shared/services/NetworkService.ts +++ b/src/shared/services/NetworkService.ts @@ -13,6 +13,7 @@ import { ComplexRequest, ComplexResponse, createSafeRegisterFn, + RequestHandlerType, UnsubPromiseAsync, UnsubscriberAsync, } from '@shared/util/PapiUtil'; @@ -21,39 +22,6 @@ import * as ConnectionService from '@shared/services/ConnectionService'; import { isClient, isRenderer, isServer } from '@shared/util/InternalUtil'; import logger from '@shared/util/logger'; -/** Whether this service has finished setting up */ -let isInitialized = false; - -/** Promise that resolves when this service is finished initializing */ -let initializePromise: Promise | undefined; - -/** Map of requestType to registered handler for that request or (on server) information about which connection to send the request */ -const requestRegistrations = new Map(); - -/** Request handler that is a local function and can be handled locally */ -type LocalRequestRegistration = { - registrationType: 'local'; - requestType: string; - handlerType: RequestHandlerType; - handler: - | RoutedRequestHandler - | RoutedRequestHandler; -}; - -/** Request handler that is not on this network service and must be requested on the network. Server-only as clients will all just send to the server */ -type RemoteRequestRegistration = { - registrationType: 'remote'; - requestType: string; - clientId: number; -}; - -/** Information about the request handler and how to run it */ -// Any is probably fine because we likely never know or care about the args or return -// eslint-disable-next-line @typescript-eslint/no-explicit-any -type RequestRegistration = - | LocalRequestRegistration - | RemoteRequestRegistration; - /** * Args handler function for a request. Called when a request is handled. * The function should accept the spread of the contents array of the request as its parameters. @@ -100,12 +68,38 @@ type RoutedRequestHandler = | ContentsRequestHandler | ComplexRequestHandler; -/** Type of request handler - indicates what type of parameters and what return type the handler has */ -enum RequestHandlerType { - Args = 'args', - Contents = 'contents', - Complex = 'complex', -} +/** Request handler that is a local function and can be handled locally */ +type LocalRequestRegistration = { + registrationType: 'local'; + requestType: string; + handlerType: RequestHandlerType; + handler: + | RoutedRequestHandler + | RoutedRequestHandler; +}; + +/** Request handler that is not on this network service and must be requested on the network. Server-only as clients will all just send to the server */ +type RemoteRequestRegistration = { + registrationType: 'remote'; + requestType: string; + clientId: number; +}; + +/** Information about the request handler and how to run it */ +// Any is probably fine because we likely never know or care about the args or return +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type RequestRegistration = + | LocalRequestRegistration + | RemoteRequestRegistration; + +/** Whether this service has finished setting up */ +let isInitialized = false; + +/** Promise that resolves when this service is finished initializing */ +let initializePromise: Promise | undefined; + +/** Map of requestType to registered handler for that request or (on server) information about which connection to send the request */ +const requestRegistrations = new Map(); // #region Private unsafe functions (do not call manually outside of initialization) diff --git a/src/shared/util/PapiUtil.ts b/src/shared/util/PapiUtil.ts index 46f262f11c..308f0c96b4 100644 --- a/src/shared/util/PapiUtil.ts +++ b/src/shared/util/PapiUtil.ts @@ -195,7 +195,7 @@ export type RequestType = { /** * Create a request message requestType string from a category and a directive * @param category the general category of request - * @param directive specific idenitifer for this type of request + * @param directive specific identifier for this type of request * @returns full requestType for use in network calls */ export const serializeRequestType = ( diff --git a/src/shared/util/Util.ts b/src/shared/util/Util.ts index 7985a12881..94f3221908 100644 --- a/src/shared/util/Util.ts +++ b/src/shared/util/Util.ts @@ -24,6 +24,7 @@ export function isString(o: unknown): o is string { * @param valueSelector function to run on each item to get the value it should have in the group (like map function). If not provided, uses the item itself * @returns map of keys to groups of values corresponding to each item */ +// eslint-disable-next-line @typescript-eslint/no-unused-vars export function groupBy( items: T[], keySelector: (item: T) => K,