Skip to content

Commit ac8eb56

Browse files
committed
feat: migrate icon download from axios to fetch with enhanced timeout and error handling
1 parent 57dd7b3 commit ac8eb56

File tree

6 files changed

+126
-216
lines changed

6 files changed

+126
-216
lines changed

bin/helpers/merge.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
generateIdentifierSafeName,
99
getSafeAppName,
1010
} from '@/utils/name';
11-
import { PakeAppOptions, PlatformMap } from '@/types';
11+
import { PakeAppOptions, PlatformMap, WindowConfig } from '@/types';
1212
import { tauriConfigDirectory, npmDirectory } from '@/utils/dir';
1313

1414
export async function mergeConfig(
@@ -81,7 +81,7 @@ export async function mergeConfig(
8181

8282
const platformHideOnClose = hideOnClose ?? platform === 'darwin';
8383

84-
const tauriConfWindowOptions = {
84+
const tauriConfWindowOptions: Partial<WindowConfig> = {
8585
width,
8686
height,
8787
fullscreen,
@@ -94,7 +94,7 @@ export async function mergeConfig(
9494
disabled_web_shortcuts: disabledWebShortcuts,
9595
hide_on_close: platformHideOnClose,
9696
incognito: incognito,
97-
title: title || null,
97+
title: title,
9898
enable_wasm: wasm,
9999
enable_drag_drop: enableDragDrop,
100100
start_to_tray: startToTray && showSystemTray,

bin/options/icon.ts

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import path from 'path';
2-
import axios from 'axios';
32
import fsExtra from 'fs-extra';
43
import chalk from 'chalk';
54
import { dir } from 'tmp-promise';
@@ -456,27 +455,46 @@ export async function downloadIcon(
456455
showSpinner = true,
457456
customTimeout?: number,
458457
): Promise<string | null> {
458+
const controller = new AbortController();
459+
const timeoutId = setTimeout(() => {
460+
controller.abort();
461+
}, customTimeout || 10000);
462+
459463
try {
460-
const response = await axios.get(iconUrl, {
461-
responseType: 'arraybuffer',
462-
timeout: customTimeout || 10000,
464+
const response = await fetch(iconUrl, {
465+
signal: controller.signal,
463466
});
464467

465-
const iconData = response.data;
466-
if (!iconData || iconData.byteLength < ICON_CONFIG.minFileSize) return null;
468+
clearTimeout(timeoutId);
469+
470+
if (!response.ok) {
471+
if (response.status === 404 && !showSpinner) {
472+
return null;
473+
}
474+
throw new Error(`HTTP ${response.status} ${response.statusText}`);
475+
}
467476

468-
const fileDetails = await fileTypeFromBuffer(iconData);
477+
const arrayBuffer = await response.arrayBuffer();
478+
479+
if (!arrayBuffer || arrayBuffer.byteLength < ICON_CONFIG.minFileSize) return null;
480+
481+
const fileDetails = await fileTypeFromBuffer(arrayBuffer);
469482
if (
470483
!fileDetails ||
471484
!ICON_CONFIG.supportedFormats.includes(fileDetails.ext as any)
472485
) {
473486
return null;
474487
}
475488

476-
return await saveIconFile(iconData, fileDetails.ext);
489+
return await saveIconFile(arrayBuffer, fileDetails.ext);
477490
} catch (error: unknown) {
478-
if (showSpinner && !((error as any).response?.status === 404)) {
479-
logger.error('Icon download failed!', error);
491+
clearTimeout(timeoutId);
492+
if (showSpinner) {
493+
if (error instanceof Error && error.name === 'AbortError') {
494+
logger.error('Icon download timed out!');
495+
} else {
496+
logger.error('Icon download failed!', error instanceof Error ? error.message : String(error));
497+
}
480498
}
481499
return null;
482500
}

bin/types.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,44 @@ export interface PakeCliOptions {
119119
export interface PakeAppOptions extends PakeCliOptions {
120120
identifier: string;
121121
}
122+
123+
export interface PlatformSpecific<T> {
124+
macos: T;
125+
linux: T;
126+
windows: T;
127+
}
128+
129+
export interface WindowConfig {
130+
url: string;
131+
hide_title_bar: boolean;
132+
fullscreen: boolean;
133+
maximize: boolean;
134+
width: number;
135+
height: number;
136+
resizable: boolean;
137+
url_type: string;
138+
always_on_top: boolean;
139+
dark_mode: boolean;
140+
disabled_web_shortcuts: boolean;
141+
activation_shortcut: string;
142+
hide_on_close: boolean;
143+
incognito: boolean;
144+
title?: string;
145+
enable_wasm: boolean;
146+
enable_drag_drop: boolean;
147+
start_to_tray: boolean;
148+
force_internal_navigation: boolean;
149+
zoom: number;
150+
min_width: number;
151+
min_height: number;
152+
ignore_certificate_errors: boolean;
153+
}
154+
155+
export interface PakeConfig {
156+
windows: WindowConfig[];
157+
user_agent: PlatformSpecific<string>;
158+
system_tray: PlatformSpecific<boolean>;
159+
system_tray_path: string;
160+
proxy_url: string;
161+
multi_instance: boolean;
162+
}

dist/cli.js

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import http from 'http';
1414
import { promisify } from 'util';
1515
import fs from 'fs';
1616
import updateNotifier from 'update-notifier';
17-
import axios from 'axios';
1817
import { dir } from 'tmp-promise';
1918
import { fileTypeFromBuffer } from 'file-type';
2019
import icongen from 'icon-gen';
@@ -385,7 +384,7 @@ async function mergeConfig(url, options, tauriConf) {
385384
disabled_web_shortcuts: disabledWebShortcuts,
386385
hide_on_close: platformHideOnClose,
387386
incognito: incognito,
388-
title: title || null,
387+
title: title,
389388
enable_wasm: wasm,
390389
enable_drag_drop: enableDragDrop,
391390
start_to_tray: startToTray && showSystemTray,
@@ -1302,7 +1301,6 @@ var license = "MIT";
13021301
var dependencies = {
13031302
"@tauri-apps/api": "^2.9.0",
13041303
"@tauri-apps/cli": "^2.9.0",
1305-
axios: "^1.12.2",
13061304
chalk: "^5.6.2",
13071305
commander: "^12.1.0",
13081306
execa: "^9.6.0",
@@ -1705,24 +1703,40 @@ async function tryGetFavicon(url, appName) {
17051703
* Downloads icon from URL
17061704
*/
17071705
async function downloadIcon(iconUrl, showSpinner = true, customTimeout) {
1706+
const controller = new AbortController();
1707+
const timeoutId = setTimeout(() => {
1708+
controller.abort();
1709+
}, customTimeout || 10000);
17081710
try {
1709-
const response = await axios.get(iconUrl, {
1710-
responseType: 'arraybuffer',
1711-
timeout: customTimeout || 10000,
1711+
const response = await fetch(iconUrl, {
1712+
signal: controller.signal,
17121713
});
1713-
const iconData = response.data;
1714-
if (!iconData || iconData.byteLength < ICON_CONFIG.minFileSize)
1714+
clearTimeout(timeoutId);
1715+
if (!response.ok) {
1716+
if (response.status === 404 && !showSpinner) {
1717+
return null;
1718+
}
1719+
throw new Error(`HTTP ${response.status} ${response.statusText}`);
1720+
}
1721+
const arrayBuffer = await response.arrayBuffer();
1722+
if (!arrayBuffer || arrayBuffer.byteLength < ICON_CONFIG.minFileSize)
17151723
return null;
1716-
const fileDetails = await fileTypeFromBuffer(iconData);
1724+
const fileDetails = await fileTypeFromBuffer(arrayBuffer);
17171725
if (!fileDetails ||
17181726
!ICON_CONFIG.supportedFormats.includes(fileDetails.ext)) {
17191727
return null;
17201728
}
1721-
return await saveIconFile(iconData, fileDetails.ext);
1729+
return await saveIconFile(arrayBuffer, fileDetails.ext);
17221730
}
17231731
catch (error) {
1724-
if (showSpinner && !(error.response?.status === 404)) {
1725-
logger.error('Icon download failed!', error);
1732+
clearTimeout(timeoutId);
1733+
if (showSpinner) {
1734+
if (error instanceof Error && error.name === 'AbortError') {
1735+
logger.error('Icon download timed out!');
1736+
}
1737+
else {
1738+
logger.error('Icon download failed!', error instanceof Error ? error.message : String(error));
1739+
}
17261740
}
17271741
return null;
17281742
}

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@
5252
"dependencies": {
5353
"@tauri-apps/api": "^2.9.0",
5454
"@tauri-apps/cli": "^2.9.0",
55-
"axios": "^1.12.2",
5655
"chalk": "^5.6.2",
5756
"commander": "^12.1.0",
5857
"execa": "^9.6.0",

0 commit comments

Comments
 (0)