diff --git a/package.json b/package.json index f529068ba..ab3c600b2 100644 --- a/package.json +++ b/package.json @@ -106,6 +106,7 @@ "class-variance-authority": "0.7.0", "clsx": "2.1.1", "date-fns": "3.6.0", + "electron-log": "5.1.6", "electron-updater": "6.3.0", "final-form": "4.20.10", "menubar": "9.5.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c561943d8..cd44f1d5e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,6 +26,9 @@ importers: date-fns: specifier: 3.6.0 version: 3.6.0 + electron-log: + specifier: 5.1.6 + version: 5.1.6 electron-updater: specifier: 6.3.0 version: 6.3.0 @@ -1373,6 +1376,10 @@ packages: engines: {node: '>=14.0.0'} hasBin: true + electron-log@5.1.6: + resolution: {integrity: sha512-o7+gNnlth67wexW7ym4niGAghXE5GZ7J1bhdNBSnqGeiMQwJ0Mhr7/HtDw2m/2thCngaOsvfjU5FDZs81TCcXw==} + engines: {node: '>= 14'} + electron-positioner@4.1.0: resolution: {integrity: sha512-726DfbI9ZNoCg+Fcu6XLuTKTnzf+6nFqv7h+K/V6Ug7IbaPMI7s9S8URnGtWFCy5N5PL4HSzRFF2mXuinftDdg==} @@ -4736,6 +4743,8 @@ snapshots: - electron-builder-squirrel-windows - supports-color + electron-log@5.1.6: {} + electron-positioner@4.1.0: {} electron-publish@24.13.1: diff --git a/src/electron/first-run.js b/src/electron/first-run.js index c81ff2b71..d93826db4 100644 --- a/src/electron/first-run.js +++ b/src/electron/first-run.js @@ -1,7 +1,7 @@ const { app, dialog } = require('electron'); - const fs = require('node:fs'); const path = require('node:path'); +const log = require('electron-log'); async function onFirstRunMaybe() { if (isFirstRun()) { @@ -49,7 +49,7 @@ function isFirstRun() { fs.writeFileSync(configPath, ''); } catch (error) { - console.warn('First run: Unable to write firstRun file', error); + log.warn('First run: Unable to write firstRun file', error); } return true; diff --git a/src/electron/main.js b/src/electron/main.js index 7e5385756..4a9bca5f3 100644 --- a/src/electron/main.js +++ b/src/electron/main.js @@ -9,6 +9,10 @@ const { menubar } = require('menubar'); const { autoUpdater } = require('electron-updater'); const { onFirstRunMaybe } = require('./first-run'); const path = require('node:path'); +const log = require('electron-log'); + +log.initialize(); +autoUpdater.logger = log; // TODO: Remove @electron/remote use - see #650 require('@electron/remote/main').initialize(); diff --git a/src/utils/api/client.test.ts b/src/utils/api/client.test.ts index 930ee9c0d..614758c16 100644 --- a/src/utils/api/client.test.ts +++ b/src/utils/api/client.test.ts @@ -1,4 +1,5 @@ import axios, { type AxiosPromise, type AxiosResponse } from 'axios'; +import log from 'electron-log'; import { mockGitHubCloudAccount, mockGitHubEnterpriseServerAccount, @@ -278,7 +279,7 @@ describe('utils/api/client.ts', () => { }); it('should handle error', async () => { - const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(); + const logErrorSpy = jest.spyOn(log, 'error').mockImplementation(); const apiRequestAuthMock = jest.spyOn(apiRequests, 'apiRequestAuth'); @@ -291,7 +292,7 @@ describe('utils/api/client.ts', () => { '123' as Token, ); - expect(consoleErrorSpy).toHaveBeenCalledWith('Failed to get html url'); + expect(logErrorSpy).toHaveBeenCalledWith('Failed to get html url'); }); }); }); diff --git a/src/utils/api/client.ts b/src/utils/api/client.ts index daf0a410e..c558b24bb 100644 --- a/src/utils/api/client.ts +++ b/src/utils/api/client.ts @@ -1,4 +1,5 @@ import type { AxiosPromise } from 'axios'; +import log from 'electron-log'; import { print } from 'graphql/language/printer'; import type { Account, @@ -224,7 +225,7 @@ export async function getHtmlUrl(url: Link, token: Token): Promise { const response = (await apiRequestAuth(url, 'GET', token)).data; return response.html_url; } catch (err) { - console.error('Failed to get html url'); + log.error('Failed to get html url'); } } diff --git a/src/utils/auth/migration.test.ts b/src/utils/auth/migration.test.ts index 82c256698..4eb2dc59b 100644 --- a/src/utils/auth/migration.test.ts +++ b/src/utils/auth/migration.test.ts @@ -1,4 +1,5 @@ import axios from 'axios'; +import log from 'electron-log'; import nock from 'nock'; import { mockGitifyUser, mockToken } from '../../__mocks__/state-mocks'; import type { AuthState, Hostname } from '../../types'; @@ -20,6 +21,7 @@ describe('utils/auth/migration.ts', () => { describe('migrateAuthenticatedAccounts', () => { it('migrate and save legacy accounts', async () => { + const logInfoSpy = jest.spyOn(log, 'info').mockImplementation(); jest.spyOn(localStorage.__proto__, 'getItem').mockReturnValueOnce( JSON.stringify({ auth: { @@ -36,7 +38,7 @@ describe('utils/auth/migration.ts', () => { await migrateAuthenticatedAccounts(); expect(localStorage.setItem).toHaveBeenCalledTimes(1); - expect(console.log).toHaveBeenCalledTimes(2); + expect(logInfoSpy).toHaveBeenCalledTimes(2); }); }); diff --git a/src/utils/auth/migration.ts b/src/utils/auth/migration.ts index a981b4aec..018b3d9ff 100644 --- a/src/utils/auth/migration.ts +++ b/src/utils/auth/migration.ts @@ -1,13 +1,9 @@ +import log from 'electron-log'; import type { Account, AuthState } from '../../types'; import Constants from '../constants'; import { loadState, saveState } from '../storage'; import { getUserData } from './utils'; -export function logMigrationProgress(msg: string) { - // biome-ignore lint/suspicious/noConsoleLog: log migration progress - console.log(`Account Migration: ${msg}`); -} - /** * Migrate authenticated accounts from old data structure to new data structure (v5.7.0+). * @@ -16,17 +12,20 @@ export function logMigrationProgress(msg: string) { export async function migrateAuthenticatedAccounts() { const existing = loadState(); - if (hasAccountsToMigrate(existing.auth)) { - logMigrationProgress('Commencing authenticated accounts migration'); + if (!hasAccountsToMigrate(existing.auth)) { + log.info('Account Migration: No accounts need migrating'); + return; + } + + log.info('Account Migration: Commencing authenticated accounts migration'); - const migratedAccounts = await convertAccounts(existing.auth); + const migratedAccounts = await convertAccounts(existing.auth); - saveState({ - auth: { ...existing.auth, accounts: migratedAccounts }, - settings: existing.settings, - }); - logMigrationProgress('Authenticated accounts migration complete'); - } + saveState({ + auth: { ...existing.auth, accounts: migratedAccounts }, + settings: existing.settings, + }); + log.info('Account Migration: Authenticated accounts migration complete'); } export function hasAccountsToMigrate(existingAuthState: AuthState): boolean { diff --git a/src/utils/subject.test.ts b/src/utils/subject.test.ts index bb53ac8c9..7aa7d814f 100644 --- a/src/utils/subject.test.ts +++ b/src/utils/subject.test.ts @@ -30,6 +30,7 @@ const mockDiscussionAuthor: DiscussionAuthor = { avatar_url: 'https://avatars.githubusercontent.com/u/123456789?v=4' as Link, type: 'User', }; +import log from 'electron-log'; describe('utils/subject.ts', () => { beforeEach(() => { @@ -1150,9 +1151,7 @@ describe('utils/subject.ts', () => { describe('Error', () => { it('catches error and logs message', async () => { - const consoleErrorSpy = jest - .spyOn(console, 'error') - .mockImplementation(); + const logErrorSpy = jest.spyOn(log, 'error').mockImplementation(); const mockError = new Error('Test error'); const mockNotification = partialMockNotification({ @@ -1167,7 +1166,7 @@ describe('utils/subject.ts', () => { await getGitifySubjectDetails(mockNotification); - expect(consoleErrorSpy).toHaveBeenCalledWith( + expect(logErrorSpy).toHaveBeenCalledWith( 'Error occurred while fetching details for Issue notification: This issue will throw an error', mockError, ); diff --git a/src/utils/subject.ts b/src/utils/subject.ts index a4063c0a3..065a71940 100644 --- a/src/utils/subject.ts +++ b/src/utils/subject.ts @@ -1,3 +1,4 @@ +import log from 'electron-log'; import type { Link } from '../types'; import type { CheckSuiteAttributes, @@ -48,7 +49,7 @@ export async function getGitifySubjectDetails( return null; } } catch (err) { - console.error( + log.error( `Error occurred while fetching details for ${notification.subject.type} notification: ${notification.subject.title}`, err, );