pake-cli 3.2.0-beta15 → 3.2.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +177 -173
- package/dist/dev.js +295 -280
- package/dist/dev.js.map +1 -1
- package/package.json +6 -8
- package/src-tauri/.cargo/config.toml +4 -8
- package/src-tauri/.pake/pake.json +4 -4
- package/src-tauri/.pake/tauri.conf.json +5 -5
- package/src-tauri/.pake/tauri.linux.conf.json +1 -4
- package/src-tauri/.pake/tauri.macos.conf.json +3 -3
- package/src-tauri/src/app/window.rs +1 -5
- package/src-tauri/tauri.linux.conf.json +1 -4
package/dist/cli.js
CHANGED
|
@@ -4,11 +4,11 @@ import { InvalidArgumentError, program, Option } from 'commander';
|
|
|
4
4
|
import log from 'loglevel';
|
|
5
5
|
import path from 'path';
|
|
6
6
|
import fsExtra from 'fs-extra';
|
|
7
|
+
import { fileURLToPath } from 'url';
|
|
7
8
|
import prompts from 'prompts';
|
|
8
9
|
import { execa, execaSync } from 'execa';
|
|
9
10
|
import crypto from 'crypto';
|
|
10
11
|
import ora from 'ora';
|
|
11
|
-
import { fileURLToPath } from 'url';
|
|
12
12
|
import dns from 'dns';
|
|
13
13
|
import http from 'http';
|
|
14
14
|
import { promisify } from 'util';
|
|
@@ -22,7 +22,7 @@ import sharp from 'sharp';
|
|
|
22
22
|
import * as psl from 'psl';
|
|
23
23
|
|
|
24
24
|
var name = "pake-cli";
|
|
25
|
-
var version
|
|
25
|
+
var version = "3.2.12";
|
|
26
26
|
var description = "🤱🏻 Turn any webpage into a desktop app with Rust. 🤱🏻 利用 Rust 轻松构建轻量级多端桌面应用。";
|
|
27
27
|
var engines = {
|
|
28
28
|
node: ">=16.0.0"
|
|
@@ -56,15 +56,13 @@ var scripts = {
|
|
|
56
56
|
build: "npm run tauri build --",
|
|
57
57
|
"build:debug": "npm run tauri build -- --debug",
|
|
58
58
|
"build:mac": "npm run tauri build -- --target universal-apple-darwin",
|
|
59
|
-
"build:config": "chmod +x
|
|
59
|
+
"build:config": "chmod +x scripts/configure-tauri.mjs && node scripts/configure-tauri.mjs",
|
|
60
60
|
analyze: "cd src-tauri && cargo bloat --release --crates",
|
|
61
61
|
tauri: "tauri",
|
|
62
|
-
cli: "rollup -c
|
|
63
|
-
"cli:
|
|
64
|
-
"cli:build
|
|
65
|
-
|
|
66
|
-
format: "prettier --write . --ignore-unknown && cd src-tauri && cargo fmt --verbose",
|
|
67
|
-
"hooks:setup": "bash .githooks/setup.sh",
|
|
62
|
+
cli: "cross-env NODE_ENV=development rollup -c -w",
|
|
63
|
+
"cli:build": "cross-env NODE_ENV=production rollup -c",
|
|
64
|
+
test: "npm run cli:build && cross-env PAKE_CREATE_APP=1 node tests/index.js",
|
|
65
|
+
format: "prettier --write . --ignore-unknown && find tests -name '*.js' -exec sed -i '' 's/[[:space:]]*$//' {} \\; && cd src-tauri && cargo fmt --verbose",
|
|
68
66
|
prepublishOnly: "npm run cli:build"
|
|
69
67
|
};
|
|
70
68
|
var type = "module";
|
|
@@ -110,7 +108,7 @@ var devDependencies = {
|
|
|
110
108
|
};
|
|
111
109
|
var packageJson = {
|
|
112
110
|
name: name,
|
|
113
|
-
version: version
|
|
111
|
+
version: version,
|
|
114
112
|
description: description,
|
|
115
113
|
engines: engines,
|
|
116
114
|
bin: bin,
|
|
@@ -126,136 +124,19 @@ var packageJson = {
|
|
|
126
124
|
devDependencies: devDependencies
|
|
127
125
|
};
|
|
128
126
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
fullscreen: false,
|
|
135
|
-
width: 1200,
|
|
136
|
-
height: 780,
|
|
137
|
-
resizable: true,
|
|
138
|
-
always_on_top: false,
|
|
139
|
-
dark_mode: false,
|
|
140
|
-
activation_shortcut: "",
|
|
141
|
-
disabled_web_shortcuts: false,
|
|
142
|
-
hide_on_close: true,
|
|
143
|
-
incognito: false
|
|
144
|
-
}
|
|
145
|
-
];
|
|
146
|
-
var user_agent = {
|
|
147
|
-
macos: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.1 Safari/605.1.15",
|
|
148
|
-
linux: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36",
|
|
149
|
-
windows: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
|
|
150
|
-
};
|
|
151
|
-
var system_tray = {
|
|
152
|
-
macos: false,
|
|
153
|
-
linux: true,
|
|
154
|
-
windows: true
|
|
155
|
-
};
|
|
156
|
-
var system_tray_path = "icons/icon.png";
|
|
157
|
-
var inject = [
|
|
158
|
-
];
|
|
159
|
-
var proxy_url = "";
|
|
160
|
-
var pakeConf = {
|
|
161
|
-
windows: windows,
|
|
162
|
-
user_agent: user_agent,
|
|
163
|
-
system_tray: system_tray,
|
|
164
|
-
system_tray_path: system_tray_path,
|
|
165
|
-
inject: inject,
|
|
166
|
-
proxy_url: proxy_url
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
var productName$1 = "Weekly";
|
|
170
|
-
var identifier = "com.pake.weekly";
|
|
171
|
-
var version = "1.0.0";
|
|
172
|
-
var app = {
|
|
173
|
-
withGlobalTauri: true,
|
|
174
|
-
trayIcon: {
|
|
175
|
-
iconPath: "png/weekly_512.png",
|
|
176
|
-
iconAsTemplate: false,
|
|
177
|
-
id: "pake-tray"
|
|
178
|
-
}
|
|
179
|
-
};
|
|
180
|
-
var build = {
|
|
181
|
-
frontendDist: "../dist"
|
|
182
|
-
};
|
|
183
|
-
var CommonConf = {
|
|
184
|
-
productName: productName$1,
|
|
185
|
-
identifier: identifier,
|
|
186
|
-
version: version,
|
|
187
|
-
app: app,
|
|
188
|
-
build: build
|
|
189
|
-
};
|
|
190
|
-
|
|
191
|
-
var bundle$2 = {
|
|
192
|
-
icon: [
|
|
193
|
-
"png/weekly_256.ico",
|
|
194
|
-
"png/weekly_32.ico"
|
|
195
|
-
],
|
|
196
|
-
active: true,
|
|
197
|
-
resources: [
|
|
198
|
-
"png/weekly_32.ico"
|
|
199
|
-
],
|
|
200
|
-
targets: [
|
|
201
|
-
"msi"
|
|
202
|
-
],
|
|
203
|
-
windows: {
|
|
204
|
-
digestAlgorithm: "sha256",
|
|
205
|
-
wix: {
|
|
206
|
-
language: [
|
|
207
|
-
"en-US"
|
|
208
|
-
],
|
|
209
|
-
template: "assets/main.wxs"
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
};
|
|
213
|
-
var WinConf = {
|
|
214
|
-
bundle: bundle$2
|
|
215
|
-
};
|
|
216
|
-
|
|
217
|
-
var bundle$1 = {
|
|
218
|
-
icon: [
|
|
219
|
-
"icons/weekly.icns"
|
|
220
|
-
],
|
|
221
|
-
active: true,
|
|
222
|
-
macOS: {
|
|
223
|
-
},
|
|
224
|
-
targets: [
|
|
225
|
-
"dmg"
|
|
226
|
-
]
|
|
227
|
-
};
|
|
228
|
-
var MacConf = {
|
|
229
|
-
bundle: bundle$1
|
|
230
|
-
};
|
|
231
|
-
|
|
232
|
-
var productName = "weekly";
|
|
233
|
-
var bundle = {
|
|
234
|
-
icon: [
|
|
235
|
-
"png/weekly_512.png"
|
|
236
|
-
],
|
|
237
|
-
active: true,
|
|
238
|
-
linux: {
|
|
239
|
-
deb: {
|
|
240
|
-
depends: [
|
|
241
|
-
"curl",
|
|
242
|
-
"wget"
|
|
243
|
-
],
|
|
244
|
-
files: {
|
|
245
|
-
"/usr/share/applications/com-pake-weekly.desktop": "assets/com-pake-weekly.desktop"
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
},
|
|
249
|
-
targets: [
|
|
250
|
-
"deb",
|
|
251
|
-
"appimage"
|
|
252
|
-
]
|
|
253
|
-
};
|
|
254
|
-
var LinuxConf = {
|
|
255
|
-
productName: productName,
|
|
256
|
-
bundle: bundle
|
|
257
|
-
};
|
|
127
|
+
// Convert the current module URL to a file path
|
|
128
|
+
const currentModulePath = fileURLToPath(import.meta.url);
|
|
129
|
+
// Resolve the parent directory of the current module
|
|
130
|
+
const npmDirectory = path.join(path.dirname(currentModulePath), '..');
|
|
131
|
+
const tauriConfigDirectory = path.join(npmDirectory, 'src-tauri', '.pake');
|
|
258
132
|
|
|
133
|
+
// Load configs from npm package directory, not from project source
|
|
134
|
+
const tauriSrcDir = path.join(npmDirectory, 'src-tauri');
|
|
135
|
+
const pakeConf = fsExtra.readJSONSync(path.join(tauriSrcDir, 'pake.json'));
|
|
136
|
+
const CommonConf = fsExtra.readJSONSync(path.join(tauriSrcDir, 'tauri.conf.json'));
|
|
137
|
+
const WinConf = fsExtra.readJSONSync(path.join(tauriSrcDir, 'tauri.windows.conf.json'));
|
|
138
|
+
const MacConf = fsExtra.readJSONSync(path.join(tauriSrcDir, 'tauri.macos.conf.json'));
|
|
139
|
+
const LinuxConf = fsExtra.readJSONSync(path.join(tauriSrcDir, 'tauri.linux.conf.json'));
|
|
259
140
|
const platformConfigs = {
|
|
260
141
|
win32: WinConf,
|
|
261
142
|
darwin: MacConf,
|
|
@@ -315,12 +196,6 @@ const IS_MAC = platform$1 === 'darwin';
|
|
|
315
196
|
const IS_WIN = platform$1 === 'win32';
|
|
316
197
|
const IS_LINUX = platform$1 === 'linux';
|
|
317
198
|
|
|
318
|
-
// Convert the current module URL to a file path
|
|
319
|
-
const currentModulePath = fileURLToPath(import.meta.url);
|
|
320
|
-
// Resolve the parent directory of the current module
|
|
321
|
-
const npmDirectory = path.join(path.dirname(currentModulePath), '..');
|
|
322
|
-
const tauriConfigDirectory = path.join(npmDirectory, 'src-tauri', '.pake');
|
|
323
|
-
|
|
324
199
|
async function shellExec(command, timeout = 300000, env) {
|
|
325
200
|
try {
|
|
326
201
|
const { exitCode } = await execa(command, {
|
|
@@ -532,7 +407,34 @@ async function mergeConfig(url, options, tauriConf) {
|
|
|
532
407
|
tauriConf.pake.system_tray[currentPlatform] = showSystemTray;
|
|
533
408
|
// Processing targets are currently only open to Linux.
|
|
534
409
|
if (platform === 'linux') {
|
|
410
|
+
// Remove hardcoded desktop files and regenerate with correct app name
|
|
535
411
|
delete tauriConf.bundle.linux.deb.files;
|
|
412
|
+
// Generate correct desktop file configuration
|
|
413
|
+
const appNameLower = name.toLowerCase();
|
|
414
|
+
const identifier = `com.pake.${appNameLower}`;
|
|
415
|
+
const desktopFileName = `${identifier}.desktop`;
|
|
416
|
+
// Create desktop file content
|
|
417
|
+
const desktopContent = `[Desktop Entry]
|
|
418
|
+
Version=1.0
|
|
419
|
+
Type=Application
|
|
420
|
+
Name=${name}
|
|
421
|
+
Comment=${name}
|
|
422
|
+
Exec=${appNameLower}
|
|
423
|
+
Icon=${appNameLower}
|
|
424
|
+
Categories=Network;WebBrowser;
|
|
425
|
+
MimeType=text/html;text/xml;application/xhtml_xml;
|
|
426
|
+
StartupNotify=true
|
|
427
|
+
`;
|
|
428
|
+
// Write desktop file to src-tauri/assets directory where Tauri expects it
|
|
429
|
+
const srcAssetsDir = path.join(npmDirectory, 'src-tauri/assets');
|
|
430
|
+
const srcDesktopFilePath = path.join(srcAssetsDir, desktopFileName);
|
|
431
|
+
await fsExtra.ensureDir(srcAssetsDir);
|
|
432
|
+
await fsExtra.writeFile(srcDesktopFilePath, desktopContent);
|
|
433
|
+
// Set up desktop file in bundle configuration
|
|
434
|
+
// Use absolute path from src-tauri directory to assets
|
|
435
|
+
tauriConf.bundle.linux.deb.files = {
|
|
436
|
+
[`/usr/share/applications/${desktopFileName}`]: `assets/${desktopFileName}`,
|
|
437
|
+
};
|
|
536
438
|
const validTargets = ['deb', 'appimage', 'rpm'];
|
|
537
439
|
if (validTargets.includes(options.targets)) {
|
|
538
440
|
tauriConf.bundle.targets = [options.targets];
|
|
@@ -541,6 +443,13 @@ async function mergeConfig(url, options, tauriConf) {
|
|
|
541
443
|
logger.warn(`✼ The target must be one of ${validTargets.join(', ')}, the default 'deb' will be used.`);
|
|
542
444
|
}
|
|
543
445
|
}
|
|
446
|
+
// Set macOS bundle targets (for app vs dmg)
|
|
447
|
+
if (platform === 'darwin') {
|
|
448
|
+
const validMacTargets = ['app', 'dmg'];
|
|
449
|
+
if (validMacTargets.includes(options.targets)) {
|
|
450
|
+
tauriConf.bundle.targets = [options.targets];
|
|
451
|
+
}
|
|
452
|
+
}
|
|
544
453
|
// Set icon.
|
|
545
454
|
const platformIconMap = {
|
|
546
455
|
win32: {
|
|
@@ -563,7 +472,7 @@ async function mergeConfig(url, options, tauriConf) {
|
|
|
563
472
|
},
|
|
564
473
|
};
|
|
565
474
|
const iconInfo = platformIconMap[platform];
|
|
566
|
-
const exists = await fsExtra.pathExists(options.icon);
|
|
475
|
+
const exists = options.icon && (await fsExtra.pathExists(options.icon));
|
|
567
476
|
if (exists) {
|
|
568
477
|
let updateIconPath = true;
|
|
569
478
|
let customIconExt = path.extname(options.icon).toLowerCase();
|
|
@@ -575,7 +484,12 @@ async function mergeConfig(url, options, tauriConf) {
|
|
|
575
484
|
else {
|
|
576
485
|
const iconPath = path.join(npmDirectory, 'src-tauri/', iconInfo.path);
|
|
577
486
|
tauriConf.bundle.resources = [iconInfo.path];
|
|
578
|
-
|
|
487
|
+
// Avoid copying if source and destination are the same
|
|
488
|
+
const absoluteIconPath = path.resolve(options.icon);
|
|
489
|
+
const absoluteDestPath = path.resolve(iconPath);
|
|
490
|
+
if (absoluteIconPath !== absoluteDestPath) {
|
|
491
|
+
await fsExtra.copy(options.icon, iconPath);
|
|
492
|
+
}
|
|
579
493
|
}
|
|
580
494
|
if (updateIconPath) {
|
|
581
495
|
tauriConf.bundle.icon = [options.icon];
|
|
@@ -651,17 +565,19 @@ class BaseBuilder {
|
|
|
651
565
|
this.options = options;
|
|
652
566
|
}
|
|
653
567
|
getBuildEnvironment() {
|
|
654
|
-
return IS_MAC
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
568
|
+
return IS_MAC
|
|
569
|
+
? {
|
|
570
|
+
CFLAGS: '-fno-modules',
|
|
571
|
+
CXXFLAGS: '-fno-modules',
|
|
572
|
+
MACOSX_DEPLOYMENT_TARGET: '14.0',
|
|
573
|
+
}
|
|
574
|
+
: undefined;
|
|
659
575
|
}
|
|
660
576
|
getInstallTimeout() {
|
|
661
577
|
return process.platform === 'win32' ? 600000 : 300000;
|
|
662
578
|
}
|
|
663
579
|
getBuildTimeout() {
|
|
664
|
-
return
|
|
580
|
+
return 900000; // 15 minutes for all builds
|
|
665
581
|
}
|
|
666
582
|
async prepare() {
|
|
667
583
|
const tauriSrcPath = path.join(npmDirectory, 'src-tauri');
|
|
@@ -692,7 +608,9 @@ class BaseBuilder {
|
|
|
692
608
|
await fsExtra.ensureDir(rustProjectDir);
|
|
693
609
|
// 统一使用npm,简单可靠
|
|
694
610
|
const packageManager = 'npm';
|
|
695
|
-
const registryOption = isChina
|
|
611
|
+
const registryOption = isChina
|
|
612
|
+
? ' --registry=https://registry.npmmirror.com'
|
|
613
|
+
: '';
|
|
696
614
|
const legacyPeerDeps = ' --legacy-peer-deps'; // 解决dependency conflicts
|
|
697
615
|
const timeout = this.getInstallTimeout();
|
|
698
616
|
const buildEnv = this.getBuildEnvironment();
|
|
@@ -722,7 +640,7 @@ class BaseBuilder {
|
|
|
722
640
|
// Build app
|
|
723
641
|
const buildSpinner = getSpinner('Building app...');
|
|
724
642
|
// Let spinner run for a moment so user can see it, then stop before npm command
|
|
725
|
-
await new Promise(resolve => setTimeout(resolve, 500));
|
|
643
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
726
644
|
buildSpinner.stop();
|
|
727
645
|
// Show static message to keep the status visible
|
|
728
646
|
logger.warn('✸ Building app...');
|
|
@@ -752,13 +670,18 @@ class BaseBuilder {
|
|
|
752
670
|
if (IS_MAC && this.options.targets === 'app') {
|
|
753
671
|
fullCommand += ' --bundles app';
|
|
754
672
|
}
|
|
673
|
+
// Add features
|
|
674
|
+
const features = ['cli-build'];
|
|
755
675
|
// Add macos-proxy feature for modern macOS (Darwin 23+ = macOS 14+)
|
|
756
676
|
if (IS_MAC) {
|
|
757
677
|
const macOSVersion = this.getMacOSMajorVersion();
|
|
758
678
|
if (macOSVersion >= 23) {
|
|
759
|
-
|
|
679
|
+
features.push('macos-proxy');
|
|
760
680
|
}
|
|
761
681
|
}
|
|
682
|
+
if (features.length > 0) {
|
|
683
|
+
fullCommand += ` --features ${features.join(',')}`;
|
|
684
|
+
}
|
|
762
685
|
return fullCommand;
|
|
763
686
|
}
|
|
764
687
|
getMacOSMajorVersion() {
|
|
@@ -812,9 +735,26 @@ class MacBuilder extends BaseBuilder {
|
|
|
812
735
|
return `${name}_${tauriConfig.version}_${arch}`;
|
|
813
736
|
}
|
|
814
737
|
getBuildCommand() {
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
738
|
+
if (this.options.multiArch) {
|
|
739
|
+
const baseCommand = this.options.debug
|
|
740
|
+
? 'npm run tauri build -- --debug'
|
|
741
|
+
: 'npm run tauri build --';
|
|
742
|
+
// Use temporary config directory to avoid modifying source files
|
|
743
|
+
const configPath = path.join('src-tauri', '.pake', 'tauri.conf.json');
|
|
744
|
+
let fullCommand = `${baseCommand} --target universal-apple-darwin -c "${configPath}"`;
|
|
745
|
+
// Add features
|
|
746
|
+
const features = ['cli-build'];
|
|
747
|
+
// Add macos-proxy feature for modern macOS (Darwin 23+ = macOS 14+)
|
|
748
|
+
const macOSVersion = this.getMacOSMajorVersion();
|
|
749
|
+
if (macOSVersion >= 23) {
|
|
750
|
+
features.push('macos-proxy');
|
|
751
|
+
}
|
|
752
|
+
if (features.length > 0) {
|
|
753
|
+
fullCommand += ` --features ${features.join(',')}`;
|
|
754
|
+
}
|
|
755
|
+
return fullCommand;
|
|
756
|
+
}
|
|
757
|
+
return super.getBuildCommand();
|
|
818
758
|
}
|
|
819
759
|
getBasePath() {
|
|
820
760
|
return this.options.multiArch
|
|
@@ -1000,7 +940,22 @@ async function convertIconFormat(inputPath, appName) {
|
|
|
1000
940
|
async function handleIcon(options, url) {
|
|
1001
941
|
if (options.icon) {
|
|
1002
942
|
if (options.icon.startsWith('http')) {
|
|
1003
|
-
|
|
943
|
+
const downloadedPath = await downloadIcon(options.icon);
|
|
944
|
+
if (downloadedPath && options.name) {
|
|
945
|
+
// Convert downloaded icon to platform-specific format
|
|
946
|
+
const convertedPath = await convertIconFormat(downloadedPath, options.name);
|
|
947
|
+
if (convertedPath) {
|
|
948
|
+
// For Windows, copy the converted ico to the expected location
|
|
949
|
+
if (IS_WIN && convertedPath.endsWith('.ico')) {
|
|
950
|
+
const finalIconPath = path.join(npmDirectory, `src-tauri/png/${options.name.toLowerCase()}_256.ico`);
|
|
951
|
+
await fsExtra.ensureDir(path.dirname(finalIconPath));
|
|
952
|
+
await fsExtra.copy(convertedPath, finalIconPath);
|
|
953
|
+
return finalIconPath;
|
|
954
|
+
}
|
|
955
|
+
return convertedPath;
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
return downloadedPath;
|
|
1004
959
|
}
|
|
1005
960
|
return path.resolve(options.icon);
|
|
1006
961
|
}
|
|
@@ -1011,11 +966,43 @@ async function handleIcon(options, url) {
|
|
|
1011
966
|
return faviconPath;
|
|
1012
967
|
}
|
|
1013
968
|
logger.info('✼ No icon provided, using default icon.');
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
969
|
+
// For Windows, ensure we have proper fallback handling
|
|
970
|
+
if (IS_WIN) {
|
|
971
|
+
const defaultIcoPath = path.join(npmDirectory, 'src-tauri/png/icon_256.ico');
|
|
972
|
+
const defaultPngPath = path.join(npmDirectory, 'src-tauri/png/icon_512.png');
|
|
973
|
+
// First try default ico
|
|
974
|
+
if (await fsExtra.pathExists(defaultIcoPath)) {
|
|
975
|
+
return defaultIcoPath;
|
|
976
|
+
}
|
|
977
|
+
// If ico doesn't exist, try to convert from png
|
|
978
|
+
if (await fsExtra.pathExists(defaultPngPath)) {
|
|
979
|
+
logger.info('✼ Default ico not found, converting from png...');
|
|
980
|
+
try {
|
|
981
|
+
const convertedPath = await convertIconFormat(defaultPngPath, 'icon');
|
|
982
|
+
if (convertedPath && (await fsExtra.pathExists(convertedPath))) {
|
|
983
|
+
// Copy converted icon to the expected location for Windows
|
|
984
|
+
const finalIconPath = path.join(npmDirectory, 'src-tauri/png/icon_256.ico');
|
|
985
|
+
await fsExtra.ensureDir(path.dirname(finalIconPath));
|
|
986
|
+
await fsExtra.copy(convertedPath, finalIconPath);
|
|
987
|
+
return finalIconPath;
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
catch (error) {
|
|
991
|
+
logger.warn(`Failed to convert default png to ico: ${error.message}`);
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
// Last resort: return png path if it exists (Windows can handle png in some cases)
|
|
995
|
+
if (await fsExtra.pathExists(defaultPngPath)) {
|
|
996
|
+
logger.warn('✼ Using png as fallback for Windows (may cause issues).');
|
|
997
|
+
return defaultPngPath;
|
|
998
|
+
}
|
|
999
|
+
// If nothing exists, return empty string to let merge.ts handle default icon
|
|
1000
|
+
logger.warn('✼ No default icon found, will use pake default.');
|
|
1001
|
+
return '';
|
|
1002
|
+
}
|
|
1003
|
+
const iconPath = IS_LINUX
|
|
1004
|
+
? 'src-tauri/png/icon_512.png'
|
|
1005
|
+
: 'src-tauri/icons/icon.icns';
|
|
1019
1006
|
return path.join(npmDirectory, iconPath);
|
|
1020
1007
|
}
|
|
1021
1008
|
/**
|
|
@@ -1024,10 +1011,10 @@ async function handleIcon(options, url) {
|
|
|
1024
1011
|
function generateIconServiceUrls(domain) {
|
|
1025
1012
|
const logoDevUrls = API_TOKENS.logoDev
|
|
1026
1013
|
.sort(() => Math.random() - 0.5)
|
|
1027
|
-
.map(token => `https://img.logo.dev/${domain}?token=${token}&format=png&size=256`);
|
|
1014
|
+
.map((token) => `https://img.logo.dev/${domain}?token=${token}&format=png&size=256`);
|
|
1028
1015
|
const brandfetchUrls = API_TOKENS.brandfetch
|
|
1029
1016
|
.sort(() => Math.random() - 0.5)
|
|
1030
|
-
.map(key => `https://cdn.brandfetch.io/${domain}/w/400/h/400?c=${key}`);
|
|
1017
|
+
.map((key) => `https://cdn.brandfetch.io/${domain}/w/400/h/400?c=${key}`);
|
|
1031
1018
|
return [
|
|
1032
1019
|
...logoDevUrls,
|
|
1033
1020
|
...brandfetchUrls,
|
|
@@ -1051,18 +1038,33 @@ async function tryGetFavicon(url, appName) {
|
|
|
1051
1038
|
const domain = new URL(url).hostname;
|
|
1052
1039
|
const spinner = getSpinner(`Fetching icon from ${domain}...`);
|
|
1053
1040
|
const serviceUrls = generateIconServiceUrls(domain);
|
|
1041
|
+
// Use shorter timeout for CI environments
|
|
1042
|
+
const isCI = process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true';
|
|
1043
|
+
const downloadTimeout = isCI ? 5000 : ICON_CONFIG.downloadTimeout;
|
|
1054
1044
|
for (const serviceUrl of serviceUrls) {
|
|
1055
1045
|
try {
|
|
1056
|
-
const faviconPath = await downloadIcon(serviceUrl, false);
|
|
1046
|
+
const faviconPath = await downloadIcon(serviceUrl, false, downloadTimeout);
|
|
1057
1047
|
if (!faviconPath)
|
|
1058
1048
|
continue;
|
|
1059
1049
|
const convertedPath = await convertIconFormat(faviconPath, appName);
|
|
1060
1050
|
if (convertedPath) {
|
|
1051
|
+
// For Windows, copy the converted ico to the expected location
|
|
1052
|
+
if (IS_WIN && convertedPath.endsWith('.ico')) {
|
|
1053
|
+
const finalIconPath = path.join(npmDirectory, `src-tauri/png/${appName.toLowerCase()}_256.ico`);
|
|
1054
|
+
await fsExtra.ensureDir(path.dirname(finalIconPath));
|
|
1055
|
+
await fsExtra.copy(convertedPath, finalIconPath);
|
|
1056
|
+
spinner.succeed(chalk.green('Icon fetched and converted successfully!'));
|
|
1057
|
+
return finalIconPath;
|
|
1058
|
+
}
|
|
1061
1059
|
spinner.succeed(chalk.green('Icon fetched and converted successfully!'));
|
|
1062
1060
|
return convertedPath;
|
|
1063
1061
|
}
|
|
1064
1062
|
}
|
|
1065
|
-
catch {
|
|
1063
|
+
catch (error) {
|
|
1064
|
+
// Log specific errors in CI for debugging
|
|
1065
|
+
if (isCI) {
|
|
1066
|
+
logger.debug(`Icon service ${serviceUrl} failed: ${error.message}`);
|
|
1067
|
+
}
|
|
1066
1068
|
continue;
|
|
1067
1069
|
}
|
|
1068
1070
|
}
|
|
@@ -1077,17 +1079,18 @@ async function tryGetFavicon(url, appName) {
|
|
|
1077
1079
|
/**
|
|
1078
1080
|
* Downloads icon from URL
|
|
1079
1081
|
*/
|
|
1080
|
-
async function downloadIcon(iconUrl, showSpinner = true) {
|
|
1082
|
+
async function downloadIcon(iconUrl, showSpinner = true, customTimeout) {
|
|
1081
1083
|
try {
|
|
1082
1084
|
const response = await axios.get(iconUrl, {
|
|
1083
1085
|
responseType: 'arraybuffer',
|
|
1084
|
-
timeout: ICON_CONFIG.downloadTimeout,
|
|
1086
|
+
timeout: customTimeout || ICON_CONFIG.downloadTimeout,
|
|
1085
1087
|
});
|
|
1086
1088
|
const iconData = response.data;
|
|
1087
1089
|
if (!iconData || iconData.byteLength < ICON_CONFIG.minFileSize)
|
|
1088
1090
|
return null;
|
|
1089
1091
|
const fileDetails = await fileTypeFromBuffer(iconData);
|
|
1090
|
-
if (!fileDetails ||
|
|
1092
|
+
if (!fileDetails ||
|
|
1093
|
+
!ICON_CONFIG.supportedFormats.includes(fileDetails.ext)) {
|
|
1091
1094
|
return null;
|
|
1092
1095
|
}
|
|
1093
1096
|
return await saveIconFile(iconData, fileDetails.ext);
|
|
@@ -1201,7 +1204,8 @@ async function handleOptions(options, url) {
|
|
|
1201
1204
|
name,
|
|
1202
1205
|
identifier: getIdentifier(url),
|
|
1203
1206
|
};
|
|
1204
|
-
|
|
1207
|
+
const iconPath = await handleIcon(appOptions, url);
|
|
1208
|
+
appOptions.icon = iconPath || undefined;
|
|
1205
1209
|
return appOptions;
|
|
1206
1210
|
}
|
|
1207
1211
|
|