Skip to content

Commit 02e8d14

Browse files
committed
refactor: replace err as Error casts with toError utility
1 parent a2adc75 commit 02e8d14

File tree

19 files changed

+117
-85
lines changed

19 files changed

+117
-85
lines changed

src/main/handlers/storage.test.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,13 @@ vi.mock('electron', () => ({
1515
}));
1616

1717
const logErrorMock = vi.fn();
18-
vi.mock('../../shared/logger', () => ({
19-
logError: (...args: unknown[]) => logErrorMock(...args),
20-
}));
18+
vi.mock('../../shared/logger', async (importOriginal) => {
19+
const actual = await importOriginal<typeof import('../../shared/logger')>();
20+
return {
21+
...actual,
22+
logError: (...args: unknown[]) => logErrorMock(...args),
23+
};
24+
});
2125

2226
describe('main/handlers/storage.ts', () => {
2327
describe('registerStorageHandlers', () => {

src/main/handlers/storage.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { safeStorage } from 'electron';
22

33
import { EVENTS } from '../../shared/events';
4-
import { logError } from '../../shared/logger';
4+
import { logError, toError } from '../../shared/logger';
55

66
import { handleMainEvent } from '../events';
77

@@ -22,11 +22,11 @@ export function registerStorageHandlers(): void {
2222
handleMainEvent(EVENTS.SAFE_STORAGE_DECRYPT, (_, value: string) => {
2323
try {
2424
return safeStorage.decryptString(Buffer.from(value, 'base64'));
25-
} catch (err: unknown) {
25+
} catch (err) {
2626
logError(
2727
'main:safe-storage-decrypt',
2828
'Failed to decrypt value - data may be from old build',
29-
err as Error,
29+
toError(err),
3030
);
3131
throw err;
3232
}

src/main/lifecycle/first-run.test.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,13 @@ vi.mock('electron', () => ({
3535
vi.mock('../utils', () => ({ isDevMode: () => false }));
3636

3737
const logErrorMock = vi.fn();
38-
vi.mock('../../shared/logger', () => ({
39-
logError: (...a: unknown[]) => logErrorMock(...a),
40-
}));
38+
vi.mock('../../shared/logger', async (importOriginal) => {
39+
const actual = await importOriginal<typeof import('../../shared/logger')>();
40+
return {
41+
...actual,
42+
logError: (...a: unknown[]) => logErrorMock(...a),
43+
};
44+
});
4145

4246
let mac = true;
4347
vi.mock('../../shared/platform', () => ({ isMacOS: () => mac }));

src/main/lifecycle/first-run.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import path from 'node:path';
44
import { app, dialog } from 'electron';
55

66
import { APPLICATION } from '../../shared/constants';
7-
import { logError } from '../../shared/logger';
7+
import { logError, toError } from '../../shared/logger';
88
import { isMacOS } from '../../shared/platform';
99

1010
import { isDevMode } from '../utils';
@@ -74,7 +74,7 @@ function checkAndMarkFirstRun(): boolean {
7474
logError(
7575
'checkAndMarkFirstRun',
7676
'Unable to write firstRun file',
77-
err as Error,
77+
toError(err),
7878
);
7979
}
8080

src/main/updater.test.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,14 @@ import type { Menubar } from 'menubar';
44
import { APPLICATION } from '../shared/constants';
55
import { logError, logInfo } from '../shared/logger';
66

7-
vi.mock('../shared/logger', () => ({
8-
logInfo: vi.fn(),
9-
logError: vi.fn(),
10-
}));
7+
vi.mock('../shared/logger', async (importOriginal) => {
8+
const actual = await importOriginal<typeof import('../shared/logger')>();
9+
return {
10+
...actual,
11+
logInfo: vi.fn(),
12+
logError: vi.fn(),
13+
};
14+
});
1115

1216
import MenuBuilder from './menu';
1317
import AppUpdater from './updater';

src/main/updater.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { autoUpdater } from 'electron-updater';
33
import type { Menubar } from 'menubar';
44

55
import { APPLICATION } from '../shared/constants';
6-
import { logError, logInfo } from '../shared/logger';
6+
import { logError, logInfo, toError } from '../shared/logger';
77

88
import type MenuBuilder from './menu';
99

@@ -123,7 +123,7 @@ export default class AppUpdater {
123123
logInfo('app updater', 'Checking for updates on application launch');
124124
await autoUpdater.checkForUpdatesAndNotify();
125125
} catch (err) {
126-
logError('auto updater', 'Initial check failed', err as Error);
126+
logError('auto updater', 'Initial check failed', toError(err));
127127
}
128128
}
129129

@@ -136,7 +136,7 @@ export default class AppUpdater {
136136
logInfo('app updater', 'Checking for updates on a periodic schedule');
137137
await autoUpdater.checkForUpdatesAndNotify();
138138
} catch (e) {
139-
logError('auto updater', 'Scheduled check failed', e as Error);
139+
logError('auto updater', 'Scheduled check failed', toError(e));
140140
}
141141
};
142142

src/renderer/hooks/useNotifications.ts

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import {
2020
areAllAccountErrorsSame,
2121
doesAllAccountsHaveErrors,
2222
} from '../utils/core/errors';
23-
import { rendererLogError } from '../utils/core/logger';
23+
import { rendererLogError, toError } from '../utils/core/logger';
2424
import {
2525
getAllNotifications,
2626
getNotificationCount,
@@ -139,11 +139,11 @@ export const useNotifications = (): NotificationsState => {
139139
);
140140

141141
if (diffNotifications.length > 0) {
142-
if (state.settings!.playSound) {
143-
raiseSoundNotification(state.settings!.notificationVolume);
142+
if (state.settings?.playSound) {
143+
raiseSoundNotification(state.settings.notificationVolume);
144144
}
145145

146-
if (state.settings!.showNotifications) {
146+
if (state.settings?.showNotifications) {
147147
raiseNativeNotification(diffNotifications);
148148
}
149149
}
@@ -159,6 +159,10 @@ export const useNotifications = (): NotificationsState => {
159159

160160
const markNotificationsAsRead = useCallback(
161161
async (state: GitifyState, readNotifications: GitifyNotification[]) => {
162+
if (!state.settings) {
163+
return;
164+
}
165+
162166
setStatus('loading');
163167

164168
try {
@@ -170,7 +174,7 @@ export const useNotifications = (): NotificationsState => {
170174

171175
const updatedNotifications = removeNotificationsForAccount(
172176
readNotifications[0].account,
173-
state.settings!,
177+
state.settings,
174178
readNotifications,
175179
notifications,
176180
);
@@ -180,7 +184,7 @@ export const useNotifications = (): NotificationsState => {
180184
rendererLogError(
181185
'markNotificationsAsRead',
182186
'Error occurred while marking notifications as read',
183-
err as Error,
187+
toError(err),
184188
);
185189
}
186190

@@ -191,7 +195,10 @@ export const useNotifications = (): NotificationsState => {
191195

192196
const markNotificationsAsDone = useCallback(
193197
async (state: GitifyState, doneNotifications: GitifyNotification[]) => {
194-
if (!isMarkAsDoneFeatureSupported(doneNotifications[0].account)) {
198+
if (
199+
!state.settings ||
200+
!isMarkAsDoneFeatureSupported(doneNotifications[0].account)
201+
) {
195202
return;
196203
}
197204

@@ -206,7 +213,7 @@ export const useNotifications = (): NotificationsState => {
206213

207214
const updatedNotifications = removeNotificationsForAccount(
208215
doneNotifications[0].account,
209-
state.settings!,
216+
state.settings,
210217
doneNotifications,
211218
notifications,
212219
);
@@ -216,7 +223,7 @@ export const useNotifications = (): NotificationsState => {
216223
rendererLogError(
217224
'markNotificationsAsDone',
218225
'Error occurred while marking notifications as done',
219-
err as Error,
226+
toError(err),
220227
);
221228
}
222229

@@ -227,6 +234,10 @@ export const useNotifications = (): NotificationsState => {
227234

228235
const unsubscribeNotification = useCallback(
229236
async (state: GitifyState, notification: GitifyNotification) => {
237+
if (!state.settings) {
238+
return;
239+
}
240+
230241
setStatus('loading');
231242

232243
try {
@@ -235,7 +246,7 @@ export const useNotifications = (): NotificationsState => {
235246
notification.id,
236247
);
237248

238-
if (state.settings!.markAsDoneOnUnsubscribe) {
249+
if (state.settings.markAsDoneOnUnsubscribe) {
239250
await markNotificationsAsDone(state, [notification]);
240251
} else {
241252
await markNotificationsAsRead(state, [notification]);
@@ -244,7 +255,7 @@ export const useNotifications = (): NotificationsState => {
244255
rendererLogError(
245256
'unsubscribeNotification',
246257
'Error occurred while unsubscribing from notification thread',
247-
err as Error,
258+
toError(err),
248259
notification,
249260
);
250261
}

src/renderer/routes/Accounts.tsx

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import { determineFailureType } from '../utils/api/errors';
3636
import { hasAlternateScopes, hasRecommendedScopes } from '../utils/auth/scopes';
3737
import { getAccountUUID, refreshAccount } from '../utils/auth/utils';
3838
import { Errors } from '../utils/core/errors';
39+
import { toError } from '../utils/core/logger';
3940
import { saveState } from '../utils/core/storage';
4041
import {
4142
openAccountProfile,
@@ -85,7 +86,7 @@ export const AccountsRoute: FC = () => {
8586
} catch (err) {
8687
setRefreshErrorStates((prev) => ({
8788
...prev,
88-
[accountUUID]: determineFailureType(err as Error),
89+
[accountUUID]: determineFailureType(toError(err)),
8990
}));
9091
}
9192

@@ -153,8 +154,8 @@ export const AccountsRoute: FC = () => {
153154

154155
<Contents>
155156
{auth.accounts.map((account, i) => {
156-
const AuthMethodIcon = getAuthMethodIcon(account.method)!;
157-
const PlatformIcon = getPlatformIcon(account.platform)!;
157+
const AuthMethodIcon = getAuthMethodIcon(account.method);
158+
const PlatformIcon = getPlatformIcon(account.platform);
158159
const accountUUID = getAccountUUID(account);
159160
const accountError = getAccountError(account);
160161
const hasBadCredentials = accountError === Errors.BAD_CREDENTIALS;
@@ -172,10 +173,10 @@ export const AccountsRoute: FC = () => {
172173
title="Open account profile ↗"
173174
>
174175
<AvatarWithFallback
175-
alt={account.user!.login}
176-
name={`@${account.user!.login}`}
176+
alt={account.user?.login}
177+
name={`@${account.user?.login}`}
177178
size={Size.XLARGE}
178-
src={account.user!.avatar ?? undefined}
179+
src={account.user?.avatar ?? undefined}
179180
/>
180181
</Button>
181182
</Stack>
@@ -191,7 +192,7 @@ export const AccountsRoute: FC = () => {
191192
align="center"
192193
direction="horizontal"
193194
gap="condensed"
194-
hidden={!account.user!.name}
195+
hidden={!account.user?.name}
195196
>
196197
<PersonIcon />
197198
<Text>{account.user?.name}</Text>
@@ -206,7 +207,7 @@ export const AccountsRoute: FC = () => {
206207
onClick={() => openHost(account.hostname)}
207208
title="Open host ↗"
208209
>
209-
<PlatformIcon />
210+
{PlatformIcon && <PlatformIcon />}
210211
<Text>{account.hostname}</Text>
211212
</Stack>
212213

@@ -219,7 +220,7 @@ export const AccountsRoute: FC = () => {
219220
onClick={() => openDeveloperSettings(account)}
220221
title="Open developer settings ↗"
221222
>
222-
<AuthMethodIcon />
223+
{AuthMethodIcon && <AuthMethodIcon />}
223224
<Text>{account.method}</Text>
224225
</Stack>
225226

@@ -252,7 +253,7 @@ export const AccountsRoute: FC = () => {
252253

253254
{!hasBadCredentials && (
254255
<IconButton
255-
aria-label={`View scopes for ${account.user!.login}`}
256+
aria-label={`View scopes for ${account.user?.login}`}
256257
data-testid="account-view-scopes"
257258
icon={() => (
258259
<ShieldCheckIcon
@@ -282,7 +283,7 @@ export const AccountsRoute: FC = () => {
282283

283284
{hasBadCredentials && (
284285
<IconButton
285-
aria-label={`Re-authenticate ${account.user!.login}`}
286+
aria-label={`Re-authenticate ${account.user?.login}`}
286287
data-testid="account-reauthenticate"
287288
icon={KeyIcon}
288289
onClick={() => handleReAuthenticate(account)}
@@ -292,7 +293,7 @@ export const AccountsRoute: FC = () => {
292293
)}
293294

294295
<IconButton
295-
aria-label={`Refresh ${account.user!.login}`}
296+
aria-label={`Refresh ${account.user?.login}`}
296297
data-testid="account-refresh"
297298
icon={SyncIcon}
298299
loading={loadingStates[accountUUID] || false}
@@ -301,7 +302,7 @@ export const AccountsRoute: FC = () => {
301302
/>
302303

303304
<IconButton
304-
aria-label={`Logout ${account.user!.login}`}
305+
aria-label={`Logout ${account.user?.login}`}
305306
data-testid="account-logout"
306307
icon={SignOutIcon}
307308
onClick={() => logoutAccount(account)}

src/renderer/routes/LoginWithDeviceFlow.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import {
3333
getAlternateScopeNames,
3434
getRecommendedScopeNames,
3535
} from '../utils/auth/scopes';
36-
import { rendererLogError } from '../utils/core/logger';
36+
import { rendererLogError, toError } from '../utils/core/logger';
3737
import { copyToClipboard, openExternalLink } from '../utils/system/comms';
3838
import { openDeveloperSettings } from '../utils/system/links';
3939

@@ -83,7 +83,7 @@ export const LoginWithDeviceFlowRoute: FC = () => {
8383
rendererLogError(
8484
'LoginWithDeviceFlow',
8585
'Failed to start device flow',
86-
err as Error,
86+
toError(err),
8787
);
8888
setError('Failed to start authentication. Please try again.');
8989
}
@@ -130,7 +130,7 @@ export const LoginWithDeviceFlowRoute: FC = () => {
130130
rendererLogError(
131131
'LoginWithDeviceFlow',
132132
'Failed to poll device flow',
133-
err as Error,
133+
toError(err),
134134
);
135135
setError('Authentication failed. Please try again.');
136136
}

src/renderer/routes/LoginWithOAuthApp.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ import {
4242
isValidHostname,
4343
isValidToken,
4444
} from '../utils/auth/utils';
45-
import { rendererLogError } from '../utils/core/logger';
45+
import { rendererLogError, toError } from '../utils/core/logger';
4646
import { openExternalLink } from '../utils/system/comms';
4747

4848
interface LocationState {
@@ -134,7 +134,7 @@ export const LoginWithOAuthAppRoute: FC = () => {
134134
rendererLogError(
135135
'loginWithOAuthApp',
136136
'Failed to login with OAuth App',
137-
err as Error,
137+
toError(err),
138138
);
139139
setErrors({
140140
invalidCredentialsForHost: `Failed to validate provided Client ID and Secret against ${data.hostname}`,

0 commit comments

Comments
 (0)