From fb7118ff1c8f0dcd61f15e51b193512283d83fa1 Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Sun, 9 Jan 2022 22:16:29 +0100 Subject: build: Add eslint-plugin-unicorn MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kristóf Marussy --- .../src/controllers/__tests__/initConfig.spec.ts | 2 +- packages/main/src/controllers/initConfig.ts | 14 ++--- packages/main/src/devTools.ts | 3 +- packages/main/src/index.ts | 72 ++++++++++++---------- .../services/impl/ConfigPersistenceServiceImpl.ts | 24 ++++---- packages/main/src/stores/Config.ts | 9 +-- packages/main/src/utils/log.ts | 5 +- 7 files changed, 68 insertions(+), 61 deletions(-) (limited to 'packages/main/src') diff --git a/packages/main/src/controllers/__tests__/initConfig.spec.ts b/packages/main/src/controllers/__tests__/initConfig.spec.ts index 9a5f85e..11e7690 100644 --- a/packages/main/src/controllers/__tests__/initConfig.spec.ts +++ b/packages/main/src/controllers/__tests__/initConfig.spec.ts @@ -133,7 +133,7 @@ describe('when it has loaded the config', () => { }); it('should throttle saving changes to the config file', () => { - mocked(persistenceService.writeConfig).mockResolvedValue(undefined); + mocked(persistenceService.writeConfig).mockResolvedValue(); config.setThemeSource('dark'); jest.advanceTimersByTime(lessThanThrottleMs); config.setThemeSource('light'); diff --git a/packages/main/src/controllers/initConfig.ts b/packages/main/src/controllers/initConfig.ts index e83b8da..915f451 100644 --- a/packages/main/src/controllers/initConfig.ts +++ b/packages/main/src/controllers/initConfig.ts @@ -38,7 +38,7 @@ export default async function initConfig( ): Promise { log.trace('Initializing config controller'); - let lastSnapshotOnDisk: ConfigSnapshotOut | null = null; + let lastSnapshotOnDisk: ConfigSnapshotOut | undefined; async function readConfig(): Promise { const result = await persistenceService.readConfig(); @@ -46,8 +46,8 @@ export default async function initConfig( try { applySnapshot(config, result.data); lastSnapshotOnDisk = getSnapshot(config); - } catch (err) { - log.error('Failed to apply config snapshot', result.data, err); + } catch (error) { + log.error('Failed to apply config snapshot', result.data, error); } } return result.found; @@ -70,8 +70,8 @@ export default async function initConfig( debounce((snapshot) => { // We can compare snapshots by reference, since it is only recreated on store changes. if (lastSnapshotOnDisk !== snapshot) { - writeConfig().catch((err) => { - log.error('Failed to write config on config change', err); + writeConfig().catch((error) => { + log.error('Failed to write config on config change', error); }); } }, debounceTime), @@ -80,8 +80,8 @@ export default async function initConfig( const disposeWatcher = persistenceService.watchConfig(async () => { try { await readConfig(); - } catch (err) { - log.error('Failed to read config', err); + } catch (error) { + log.error('Failed to read config', error); } }, debounceTime); diff --git a/packages/main/src/devTools.ts b/packages/main/src/devTools.ts index 69f1514..4ca1bf3 100644 --- a/packages/main/src/devTools.ts +++ b/packages/main/src/devTools.ts @@ -49,7 +49,8 @@ export async function installDevToolsExtensions(): Promise { /* eslint-disable-next-line import/no-extraneous-dependencies, global-require, - @typescript-eslint/no-var-requires + @typescript-eslint/no-var-requires, + unicorn/prefer-module */ } = require('electron-devtools-installer') as typeof import('electron-devtools-installer'); await installExtension([REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS], { diff --git a/packages/main/src/index.ts b/packages/main/src/index.ts index 1f80e44..02e6cda 100644 --- a/packages/main/src/index.ts +++ b/packages/main/src/index.ts @@ -19,9 +19,9 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { arch } from 'os'; -import { join } from 'path'; -import { URL } from 'url'; +import { arch } from 'node:os'; +import path from 'node:path'; +import { URL } from 'node:url'; import { ServiceToMainIpcMessage, @@ -101,11 +101,14 @@ app.setAboutPanelOptions({ version: '', }); +// eslint-disable-next-line unicorn/prefer-module -- Electron apps run in a commonjs environment. +const thisDir = __dirname; + function getResourcePath(relativePath: string): string { - return join(__dirname, relativePath); + return path.join(thisDir, relativePath); } -const baseUrl = `file://${__dirname}`; +const baseUrl = `file://${thisDir}`; function getResourceUrl(relativePath: string): string { return new URL(relativePath, baseUrl).toString(); } @@ -117,15 +120,15 @@ const serviceInject: WebSource = { url: getResourceUrl(serviceInjectRelativePath), }; -let mainWindow: BrowserWindow | null = null; +let mainWindow: BrowserWindow | undefined; const store = createMainStore(); init(store) .then((disposeCompositionRoot) => { app.on('will-quit', disposeCompositionRoot); }) - .catch((err) => { - log.log('Failed to initialize application', err); + .catch((error) => { + log.log('Failed to initialize application', error); }); const rendererBaseUrl = getResourceUrl('../renderer/'); @@ -136,7 +139,7 @@ function shouldCancelMainWindowRequest(url: string, method: string): boolean { let normalizedUrl: string; try { normalizedUrl = new URL(url).toString(); - } catch (_err) { + } catch { return true; } if (isDevelopment) { @@ -233,7 +236,7 @@ async function createWindow(): Promise { 'from webContents', event.sender.id, ); - return null; + throw new Error('Invalid IPC call'); } return getSnapshot(store.shared); }); @@ -262,22 +265,22 @@ async function createWindow(): Promise { .then((data) => { serviceInject.code = data; }) - .catch((err) => { - log.error('Error while reloading', serviceInjectPath, err); + .catch((error) => { + log.error('Error while reloading', serviceInjectPath, error); }) .then(() => { browserView.webContents.reload(); }) - .catch((err) => { - log.error('Failed to reload browserView', err); + .catch((error) => { + log.error('Failed to reload browserView', error); }); break; default: log.error('Unexpected action from UI renderer:', actionToDispatch); break; } - } catch (err) { - log.error('Error while dispatching renderer action', rawAction, err); + } catch (error) { + log.error('Error while dispatching renderer action', rawAction, error); } }); @@ -285,9 +288,18 @@ async function createWindow(): Promise { webContents.send(MainToRendererIpcMessage.SharedStorePatch, patch); }); - ipcMain.handle(ServiceToMainIpcMessage.ApiExposedInMainWorld, (event) => - event.sender.id === browserView.webContents.id ? serviceInject : null, - ); + ipcMain.handle(ServiceToMainIpcMessage.ApiExposedInMainWorld, (event) => { + if (event.sender.id !== browserView.webContents.id) { + log.warn( + 'Unexpected', + ServiceToMainIpcMessage.ApiExposedInMainWorld, + 'from webContents', + event.sender.id, + ); + throw new Error('Invalid IPC call'); + } + return serviceInject; + }); browserView.webContents.on('ipc-message', (_event, channel, ...args) => { try { @@ -303,8 +315,8 @@ async function createWindow(): Promise { log.error('Unknown IPC message:', channel, args); break; } - } catch (err) { - log.error('Error while processing IPC message:', channel, args, err); + } catch (error) { + log.error('Error while processing IPC message:', channel, args, error); } }); @@ -316,9 +328,7 @@ async function createWindow(): Promise { browserView.webContents.session.webRequest.onBeforeSendHeaders( ({ url, requestHeaders }, callback) => { - const requestUserAgent = url.match( - /^[^:]+:\/\/accounts\.google\.[^./]+\//, - ) + const requestUserAgent = /^[^:]+:\/\/accounts\.google\.[^./]+\//.test(url) ? chromelessUserAgent : userAgent; callback({ @@ -332,15 +342,15 @@ async function createWindow(): Promise { browserView.webContents .loadURL('https://gitlab.com/say-hi-to-sophie/sophie') - .catch((err) => { - log.error('Failed to load browser', err); + .catch((error) => { + log.error('Failed to load browser', error); }); return mainWindow.loadURL(pageUrl); } app.on('second-instance', () => { - if (mainWindow !== null) { + if (mainWindow !== undefined) { if (!mainWindow.isVisible()) { mainWindow.show(); } @@ -363,14 +373,14 @@ app if (isDevelopment) { try { await installDevToolsExtensions(); - } catch (err) { - log.error('Failed to install devtools extensions', err); + } catch (error) { + log.error('Failed to install devtools extensions', error); } } return createWindow(); }) - .catch((err) => { - log.error('Failed to create window', err); + .catch((error) => { + log.error('Failed to create window', error); process.exit(1); }); diff --git a/packages/main/src/services/impl/ConfigPersistenceServiceImpl.ts b/packages/main/src/services/impl/ConfigPersistenceServiceImpl.ts index e92f706..a11a9da 100644 --- a/packages/main/src/services/impl/ConfigPersistenceServiceImpl.ts +++ b/packages/main/src/services/impl/ConfigPersistenceServiceImpl.ts @@ -17,9 +17,9 @@ * * SPDX-License-Identifier: AGPL-3.0-only */ -import { watch } from 'fs'; -import { readFile, stat, writeFile } from 'fs/promises'; -import { join } from 'path'; +import { watch } from 'node:fs'; +import { readFile, stat, writeFile } from 'node:fs/promises'; +import path from 'node:path'; import JSON5 from 'json5'; import throttle from 'lodash-es/throttle'; @@ -39,26 +39,26 @@ export default class ConfigPersistenceServiceImpl private writingConfig = false; - private timeLastWritten: Date | null = null; + private timeLastWritten: Date | undefined; constructor( private readonly userDataDir: string, private readonly configFileName: string = 'config.json5', ) { this.configFileName = configFileName; - this.configFilePath = join(this.userDataDir, this.configFileName); + this.configFilePath = path.join(this.userDataDir, this.configFileName); } async readConfig(): Promise { let configStr; try { configStr = await readFile(this.configFilePath, 'utf8'); - } catch (err) { - if ((err as NodeJS.ErrnoException).code === 'ENOENT') { + } catch (error) { + if ((error as NodeJS.ErrnoException).code === 'ENOENT') { log.debug('Config file', this.configFilePath, 'was not found'); return { found: false }; } - throw err; + throw error; } log.info('Read config file', this.configFilePath); return { @@ -92,8 +92,8 @@ export default class ConfigPersistenceServiceImpl const stats = await stat(this.configFilePath); mtime = stats.mtime; log.trace('Config file last modified at', mtime); - } catch (err) { - if ((err as NodeJS.ErrnoException).code === 'ENOENT') { + } catch (error) { + if ((error as NodeJS.ErrnoException).code === 'ENOENT') { log.debug( 'Config file', this.configFilePath, @@ -101,11 +101,11 @@ export default class ConfigPersistenceServiceImpl ); return; } - throw err; + throw error; } if ( !this.writingConfig && - (this.timeLastWritten === null || mtime > this.timeLastWritten) + (this.timeLastWritten === undefined || mtime > this.timeLastWritten) ) { log.debug( 'Found a config file modified at', diff --git a/packages/main/src/stores/Config.ts b/packages/main/src/stores/Config.ts index 06dbdeb..ca90c0c 100644 --- a/packages/main/src/stores/Config.ts +++ b/packages/main/src/stores/Config.ts @@ -18,12 +18,7 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { - config as originalConfig, - ConfigSnapshotIn, - ConfigSnapshotOut, - ThemeSource, -} from '@sophie/shared'; +import { config as originalConfig, ThemeSource } from '@sophie/shared'; import { Instance } from 'mobx-state-tree'; export const config = originalConfig.actions((self) => ({ @@ -34,4 +29,4 @@ export const config = originalConfig.actions((self) => ({ export interface Config extends Instance {} -export type { ConfigSnapshotIn, ConfigSnapshotOut }; +export type { ConfigSnapshotIn, ConfigSnapshotOut } from '@sophie/shared'; diff --git a/packages/main/src/utils/log.ts b/packages/main/src/utils/log.ts index 5218721..0a632d8 100644 --- a/packages/main/src/utils/log.ts +++ b/packages/main/src/utils/log.ts @@ -18,8 +18,9 @@ * SPDX-License-Identifier: AGPL-3.0-only */ +// eslint-disable-next-line unicorn/import-style -- Import the type `ChalkInstance` separately. import chalk, { ChalkInstance } from 'chalk'; -import loglevel, { Logger } from 'loglevel'; +import loglevel from 'loglevel'; import prefix from 'loglevel-plugin-prefix'; if (import.meta.env?.DEV) { @@ -54,7 +55,7 @@ prefix.apply(loglevel, { }, }); -export function getLogger(loggerName: string): Logger { +export function getLogger(loggerName: string): loglevel.Logger { return loglevel.getLogger(loggerName); } -- cgit v1.2.3-54-g00ecf