pake-cli 3.4.0 โ 3.4.1
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 +54 -12
- package/package.json +1 -1
- package/src-tauri/.pake/pake.json +2 -0
- package/src-tauri/pake.json +3 -1
- package/src-tauri/src/app/config.rs +2 -0
- package/src-tauri/src/app/setup.rs +26 -3
- package/src-tauri/src/app/window.rs +12 -9
- package/src-tauri/src/lib.rs +10 -6
package/dist/cli.js
CHANGED
|
@@ -23,7 +23,7 @@ import sharp from 'sharp';
|
|
|
23
23
|
import * as psl from 'psl';
|
|
24
24
|
|
|
25
25
|
var name = "pake-cli";
|
|
26
|
-
var version = "3.4.
|
|
26
|
+
var version = "3.4.1";
|
|
27
27
|
var description = "๐คฑ๐ป Turn any webpage into a desktop app with one command. ๐คฑ๐ป ไธ้ฎๆๅ
็ฝ้กต็ๆ่ฝป้ๆก้ขๅบ็จใ";
|
|
28
28
|
var engines = {
|
|
29
29
|
node: ">=18.0.0"
|
|
@@ -201,11 +201,13 @@ const IS_MAC = platform$1 === 'darwin';
|
|
|
201
201
|
const IS_WIN = platform$1 === 'win32';
|
|
202
202
|
const IS_LINUX = platform$1 === 'linux';
|
|
203
203
|
|
|
204
|
-
async function shellExec(command, timeout = 300000, env
|
|
204
|
+
async function shellExec(command, timeout = 300000, env) {
|
|
205
205
|
try {
|
|
206
206
|
const { exitCode } = await execa(command, {
|
|
207
207
|
cwd: npmDirectory,
|
|
208
|
-
|
|
208
|
+
// Use 'inherit' to show all output directly to user in real-time.
|
|
209
|
+
// This ensures linuxdeploy and other tool outputs are visible during builds.
|
|
210
|
+
stdio: 'inherit',
|
|
209
211
|
shell: true,
|
|
210
212
|
timeout,
|
|
211
213
|
env: env ? { ...process.env, ...env } : process.env,
|
|
@@ -219,15 +221,25 @@ async function shellExec(command, timeout = 300000, env, showOutput = false) {
|
|
|
219
221
|
throw new Error(`Command timed out after ${timeout}ms: "${command}". Try increasing timeout or check network connectivity.`);
|
|
220
222
|
}
|
|
221
223
|
let errorMsg = `Error occurred while executing command "${command}". Exit code: ${exitCode}. Details: ${errorMessage}`;
|
|
224
|
+
// Provide helpful guidance for common Linux AppImage build failures
|
|
225
|
+
// caused by strip tool incompatibility with modern glibc (2.38+)
|
|
222
226
|
if (process.platform === 'linux' &&
|
|
223
227
|
(errorMessage.includes('linuxdeploy') ||
|
|
224
228
|
errorMessage.includes('appimage') ||
|
|
225
229
|
errorMessage.includes('strip'))) {
|
|
226
230
|
errorMsg +=
|
|
227
|
-
'\n\
|
|
228
|
-
'
|
|
229
|
-
'
|
|
230
|
-
'
|
|
231
|
+
'\n\nโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n' +
|
|
232
|
+
'Linux AppImage Build Failed\n' +
|
|
233
|
+
'โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n\n' +
|
|
234
|
+
'Cause: Strip tool incompatibility with glibc 2.38+\n' +
|
|
235
|
+
' (affects Debian Trixie, Arch Linux, and other modern distros)\n\n' +
|
|
236
|
+
'Quick fix:\n' +
|
|
237
|
+
' NO_STRIP=1 pake <url> --targets appimage --debug\n\n' +
|
|
238
|
+
'Alternatives:\n' +
|
|
239
|
+
' โข Use DEB format: pake <url> --targets deb\n' +
|
|
240
|
+
' โข Update binutils: sudo apt install binutils (or pacman -S binutils)\n' +
|
|
241
|
+
' โข Detailed guide: https://github.com/tw93/Pake/blob/main/docs/faq.md\n' +
|
|
242
|
+
'โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ';
|
|
231
243
|
}
|
|
232
244
|
throw new Error(errorMsg);
|
|
233
245
|
}
|
|
@@ -351,7 +363,7 @@ async function installRust() {
|
|
|
351
363
|
const rustInstallScriptForWindows = 'winget install --id Rustlang.Rustup';
|
|
352
364
|
const spinner = getSpinner('Downloading Rust...');
|
|
353
365
|
try {
|
|
354
|
-
await shellExec(IS_WIN ? rustInstallScriptForWindows : rustInstallScriptForMac, 300000, undefined
|
|
366
|
+
await shellExec(IS_WIN ? rustInstallScriptForWindows : rustInstallScriptForMac, 300000, undefined);
|
|
355
367
|
spinner.succeed(chalk.green('โ Rust installed successfully!'));
|
|
356
368
|
ensureRustEnv();
|
|
357
369
|
}
|
|
@@ -448,13 +460,14 @@ async function mergeConfig(url, options, tauriConf) {
|
|
|
448
460
|
await fsExtra.copy(sourcePath, destPath);
|
|
449
461
|
}
|
|
450
462
|
}));
|
|
451
|
-
const { width, height, fullscreen, hideTitleBar, alwaysOnTop, appVersion, darkMode, disabledWebShortcuts, activationShortcut, userAgent, showSystemTray, systemTrayIcon, useLocalFile, identifier, name, resizable = true, inject, proxyUrl, installerLanguage, hideOnClose, incognito, title, wasm, enableDragDrop, multiInstance, } = options;
|
|
463
|
+
const { width, height, fullscreen, maximize, hideTitleBar, alwaysOnTop, appVersion, darkMode, disabledWebShortcuts, activationShortcut, userAgent, showSystemTray, systemTrayIcon, useLocalFile, identifier, name, resizable = true, inject, proxyUrl, installerLanguage, hideOnClose, incognito, title, wasm, enableDragDrop, multiInstance, startToTray, } = options;
|
|
452
464
|
const { platform } = process;
|
|
453
465
|
const platformHideOnClose = hideOnClose ?? platform === 'darwin';
|
|
454
466
|
const tauriConfWindowOptions = {
|
|
455
467
|
width,
|
|
456
468
|
height,
|
|
457
469
|
fullscreen,
|
|
470
|
+
maximize,
|
|
458
471
|
resizable,
|
|
459
472
|
hide_title_bar: hideTitleBar,
|
|
460
473
|
activation_shortcut: activationShortcut,
|
|
@@ -466,6 +479,7 @@ async function mergeConfig(url, options, tauriConf) {
|
|
|
466
479
|
title: title || null,
|
|
467
480
|
enable_wasm: wasm,
|
|
468
481
|
enable_drag_drop: enableDragDrop,
|
|
482
|
+
start_to_tray: startToTray && showSystemTray,
|
|
469
483
|
};
|
|
470
484
|
Object.assign(tauriConf.pake.windows[0], { url, ...tauriConfWindowOptions });
|
|
471
485
|
tauriConf.productName = name;
|
|
@@ -774,10 +788,10 @@ class BaseBuilder {
|
|
|
774
788
|
logger.info(`โบ Located in China, using ${packageManager}/rsProxy CN mirror.`);
|
|
775
789
|
const projectCnConf = path.join(tauriSrcPath, 'rust_proxy.toml');
|
|
776
790
|
await fsExtra.copy(projectCnConf, projectConf);
|
|
777
|
-
await shellExec(`cd "${npmDirectory}" && ${packageManager} install${registryOption}${peerDepsOption}`, timeout, buildEnv
|
|
791
|
+
await shellExec(`cd "${npmDirectory}" && ${packageManager} install${registryOption}${peerDepsOption}`, timeout, buildEnv);
|
|
778
792
|
}
|
|
779
793
|
else {
|
|
780
|
-
await shellExec(`cd "${npmDirectory}" && ${packageManager} install${peerDepsOption}`, timeout, buildEnv
|
|
794
|
+
await shellExec(`cd "${npmDirectory}" && ${packageManager} install${peerDepsOption}`, timeout, buildEnv);
|
|
781
795
|
}
|
|
782
796
|
spinner.succeed(chalk.green('Package installed!'));
|
|
783
797
|
if (!tauriTargetPathExists) {
|
|
@@ -806,7 +820,16 @@ class BaseBuilder {
|
|
|
806
820
|
...this.getBuildEnvironment(),
|
|
807
821
|
...(process.env.NO_STRIP && { NO_STRIP: process.env.NO_STRIP }),
|
|
808
822
|
};
|
|
809
|
-
|
|
823
|
+
// Warn users about potential AppImage build failures on modern Linux systems.
|
|
824
|
+
// The linuxdeploy tool bundled in Tauri uses an older strip tool that doesn't
|
|
825
|
+
// recognize the .relr.dyn section introduced in glibc 2.38+.
|
|
826
|
+
if (process.platform === 'linux' && this.options.targets === 'appimage') {
|
|
827
|
+
if (!buildEnv.NO_STRIP) {
|
|
828
|
+
logger.warn('โ Building AppImage on Linux may fail due to strip incompatibility with glibc 2.38+');
|
|
829
|
+
logger.warn('โ If build fails, retry with: NO_STRIP=1 pake <url> --targets appimage');
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
await shellExec(`cd "${npmDirectory}" && ${this.getBuildCommand(packageManager)}`, this.getBuildTimeout(), buildEnv);
|
|
810
833
|
// Copy app
|
|
811
834
|
const fileName = this.getFileName();
|
|
812
835
|
const fileType = this.getFileType(target);
|
|
@@ -865,6 +888,11 @@ class BaseBuilder {
|
|
|
865
888
|
if (target) {
|
|
866
889
|
fullCommand += ` --target ${target}`;
|
|
867
890
|
}
|
|
891
|
+
// Enable verbose output in debug mode to help diagnose build issues.
|
|
892
|
+
// This provides detailed logs from Tauri CLI and bundler tools.
|
|
893
|
+
if (this.options.debug) {
|
|
894
|
+
fullCommand += ' --verbose';
|
|
895
|
+
}
|
|
868
896
|
return fullCommand;
|
|
869
897
|
}
|
|
870
898
|
/**
|
|
@@ -1178,6 +1206,12 @@ class LinuxBuilder extends BaseBuilder {
|
|
|
1178
1206
|
if (features.length > 0) {
|
|
1179
1207
|
fullCommand += ` --features ${features.join(',')}`;
|
|
1180
1208
|
}
|
|
1209
|
+
// Enable verbose output for AppImage builds when debugging or PAKE_VERBOSE is set.
|
|
1210
|
+
// AppImage builds often fail with minimal error messages from linuxdeploy,
|
|
1211
|
+
// so verbose mode helps diagnose issues like strip failures and missing dependencies.
|
|
1212
|
+
if (this.options.targets === 'appimage' && (this.options.debug || process.env.PAKE_VERBOSE)) {
|
|
1213
|
+
fullCommand += ' --verbose';
|
|
1214
|
+
}
|
|
1181
1215
|
return fullCommand;
|
|
1182
1216
|
}
|
|
1183
1217
|
getBasePath() {
|
|
@@ -1227,6 +1261,7 @@ const DEFAULT_PAKE_OPTIONS = {
|
|
|
1227
1261
|
height: 780,
|
|
1228
1262
|
width: 1200,
|
|
1229
1263
|
fullscreen: false,
|
|
1264
|
+
maximize: false,
|
|
1230
1265
|
hideTitleBar: false,
|
|
1231
1266
|
alwaysOnTop: false,
|
|
1232
1267
|
appVersion: '1.0.0',
|
|
@@ -1249,6 +1284,7 @@ const DEFAULT_PAKE_OPTIONS = {
|
|
|
1249
1284
|
enableDragDrop: false,
|
|
1250
1285
|
keepBinary: false,
|
|
1251
1286
|
multiInstance: false,
|
|
1287
|
+
startToTray: false,
|
|
1252
1288
|
};
|
|
1253
1289
|
|
|
1254
1290
|
async function checkUpdateTips() {
|
|
@@ -1731,6 +1767,9 @@ program
|
|
|
1731
1767
|
.addOption(new Option('--always-on-top', 'Always on the top level')
|
|
1732
1768
|
.default(DEFAULT_PAKE_OPTIONS.alwaysOnTop)
|
|
1733
1769
|
.hideHelp())
|
|
1770
|
+
.addOption(new Option('--maximize', 'Start window maximized')
|
|
1771
|
+
.default(DEFAULT_PAKE_OPTIONS.maximize)
|
|
1772
|
+
.hideHelp())
|
|
1734
1773
|
.addOption(new Option('--dark-mode', 'Force Mac app to use dark mode')
|
|
1735
1774
|
.default(DEFAULT_PAKE_OPTIONS.darkMode)
|
|
1736
1775
|
.hideHelp())
|
|
@@ -1774,6 +1813,9 @@ program
|
|
|
1774
1813
|
.addOption(new Option('--multi-instance', 'Allow multiple app instances')
|
|
1775
1814
|
.default(DEFAULT_PAKE_OPTIONS.multiInstance)
|
|
1776
1815
|
.hideHelp())
|
|
1816
|
+
.addOption(new Option('--start-to-tray', 'Start app minimized to tray')
|
|
1817
|
+
.default(DEFAULT_PAKE_OPTIONS.startToTray)
|
|
1818
|
+
.hideHelp())
|
|
1777
1819
|
.addOption(new Option('--installer-language <string>', 'Installer language')
|
|
1778
1820
|
.default(DEFAULT_PAKE_OPTIONS.installerLanguage)
|
|
1779
1821
|
.hideHelp())
|
package/package.json
CHANGED
package/src-tauri/pake.json
CHANGED
|
@@ -5,6 +5,7 @@ pub struct WindowConfig {
|
|
|
5
5
|
pub url: String,
|
|
6
6
|
pub hide_title_bar: bool,
|
|
7
7
|
pub fullscreen: bool,
|
|
8
|
+
pub maximize: bool,
|
|
8
9
|
pub width: f64,
|
|
9
10
|
pub height: f64,
|
|
10
11
|
pub resizable: bool,
|
|
@@ -18,6 +19,7 @@ pub struct WindowConfig {
|
|
|
18
19
|
pub title: Option<String>,
|
|
19
20
|
pub enable_wasm: bool,
|
|
20
21
|
pub enable_drag_drop: bool,
|
|
22
|
+
pub start_to_tray: bool,
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
#[derive(Debug, Serialize, Deserialize)]
|
|
@@ -3,13 +3,13 @@ use std::sync::{Arc, Mutex};
|
|
|
3
3
|
use std::time::{Duration, Instant};
|
|
4
4
|
use tauri::{
|
|
5
5
|
menu::{MenuBuilder, MenuItemBuilder},
|
|
6
|
-
tray::TrayIconBuilder,
|
|
6
|
+
tray::{TrayIconBuilder, TrayIconEvent},
|
|
7
7
|
AppHandle, Manager,
|
|
8
8
|
};
|
|
9
9
|
use tauri_plugin_global_shortcut::{GlobalShortcutExt, Shortcut};
|
|
10
10
|
use tauri_plugin_window_state::{AppHandleExt, StateFlags};
|
|
11
11
|
|
|
12
|
-
pub fn set_system_tray(app: &AppHandle, show_system_tray: bool) -> tauri::Result<()> {
|
|
12
|
+
pub fn set_system_tray(app: &AppHandle, show_system_tray: bool, tray_icon_path: &str) -> tauri::Result<()> {
|
|
13
13
|
if !show_system_tray {
|
|
14
14
|
app.remove_tray_by_id("pake-tray");
|
|
15
15
|
return Ok(());
|
|
@@ -44,7 +44,30 @@ pub fn set_system_tray(app: &AppHandle, show_system_tray: bool) -> tauri::Result
|
|
|
44
44
|
}
|
|
45
45
|
_ => (),
|
|
46
46
|
})
|
|
47
|
-
.
|
|
47
|
+
.on_tray_icon_event(|tray, event| match event {
|
|
48
|
+
TrayIconEvent::Click { button, .. } => {
|
|
49
|
+
if button == tauri::tray::MouseButton::Left {
|
|
50
|
+
if let Some(window) = tray.app_handle().get_webview_window("pake") {
|
|
51
|
+
let is_visible = window.is_visible().unwrap_or(false);
|
|
52
|
+
if is_visible {
|
|
53
|
+
window.hide().unwrap();
|
|
54
|
+
} else {
|
|
55
|
+
window.show().unwrap();
|
|
56
|
+
window.set_focus().unwrap();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
_ => {}
|
|
62
|
+
})
|
|
63
|
+
.icon(if tray_icon_path.is_empty() {
|
|
64
|
+
app.default_window_icon().unwrap_or_else(|| panic!("Failed to get default window icon")).clone()
|
|
65
|
+
} else {
|
|
66
|
+
tauri::image::Image::from_path(tray_icon_path).unwrap_or_else(|_| {
|
|
67
|
+
// If custom tray icon fails to load, fallback to default
|
|
68
|
+
app.default_window_icon().unwrap_or_else(|| panic!("Failed to get default window icon")).clone()
|
|
69
|
+
})
|
|
70
|
+
})
|
|
48
71
|
.build(app)?;
|
|
49
72
|
|
|
50
73
|
tray.set_icon_as_template(false)?;
|
|
@@ -43,6 +43,7 @@ pub fn set_window(app: &mut App, config: &PakeConfig, tauri_config: &Config) ->
|
|
|
43
43
|
.user_agent(user_agent)
|
|
44
44
|
.resizable(window_config.resizable)
|
|
45
45
|
.fullscreen(window_config.fullscreen)
|
|
46
|
+
.maximized(window_config.maximize)
|
|
46
47
|
.inner_size(window_config.width, window_config.height)
|
|
47
48
|
.always_on_top(window_config.always_on_top)
|
|
48
49
|
.incognito(window_config.incognito);
|
|
@@ -65,14 +66,7 @@ pub fn set_window(app: &mut App, config: &PakeConfig, tauri_config: &Config) ->
|
|
|
65
66
|
.additional_browser_args("--enable-unsafe-webgpu");
|
|
66
67
|
}
|
|
67
68
|
|
|
68
|
-
|
|
69
|
-
if let Ok(proxy_url) = Url::from_str(&config.proxy_url) {
|
|
70
|
-
window_builder = window_builder.proxy_url(proxy_url);
|
|
71
|
-
#[cfg(debug_assertions)]
|
|
72
|
-
println!("Proxy configured: {}", config.proxy_url);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
69
|
+
// Platform-specific configuration must be set before proxy on Windows/Linux
|
|
76
70
|
#[cfg(target_os = "macos")]
|
|
77
71
|
{
|
|
78
72
|
let title_bar_style = if window_config.hide_title_bar {
|
|
@@ -87,7 +81,7 @@ pub fn set_window(app: &mut App, config: &PakeConfig, tauri_config: &Config) ->
|
|
|
87
81
|
}
|
|
88
82
|
}
|
|
89
83
|
|
|
90
|
-
// Windows and Linux
|
|
84
|
+
// Windows and Linux: set data_directory before proxy_url
|
|
91
85
|
#[cfg(not(target_os = "macos"))]
|
|
92
86
|
{
|
|
93
87
|
window_builder = window_builder
|
|
@@ -96,5 +90,14 @@ pub fn set_window(app: &mut App, config: &PakeConfig, tauri_config: &Config) ->
|
|
|
96
90
|
.theme(None);
|
|
97
91
|
}
|
|
98
92
|
|
|
93
|
+
// Set proxy after platform-specific configs (required for Windows/Linux)
|
|
94
|
+
if !config.proxy_url.is_empty() {
|
|
95
|
+
if let Ok(proxy_url) = Url::from_str(&config.proxy_url) {
|
|
96
|
+
window_builder = window_builder.proxy_url(proxy_url);
|
|
97
|
+
#[cfg(debug_assertions)]
|
|
98
|
+
println!("Proxy configured: {}", config.proxy_url);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
99
102
|
window_builder.build().expect("Failed to build window")
|
|
100
103
|
}
|
package/src-tauri/src/lib.rs
CHANGED
|
@@ -24,6 +24,7 @@ pub fn run_app() {
|
|
|
24
24
|
let hide_on_close = pake_config.windows[0].hide_on_close;
|
|
25
25
|
let activation_shortcut = pake_config.windows[0].activation_shortcut.clone();
|
|
26
26
|
let init_fullscreen = pake_config.windows[0].fullscreen;
|
|
27
|
+
let start_to_tray = pake_config.windows[0].start_to_tray && show_system_tray; // Only valid when tray is enabled
|
|
27
28
|
let multi_instance = pake_config.multi_instance;
|
|
28
29
|
|
|
29
30
|
let window_state_plugin = WindowStatePlugin::default()
|
|
@@ -62,15 +63,18 @@ pub fn run_app() {
|
|
|
62
63
|
])
|
|
63
64
|
.setup(move |app| {
|
|
64
65
|
let window = set_window(app, &pake_config, &tauri_config);
|
|
65
|
-
set_system_tray(app.app_handle(), show_system_tray).unwrap();
|
|
66
|
+
set_system_tray(app.app_handle(), show_system_tray, &pake_config.system_tray_path).unwrap();
|
|
66
67
|
set_global_shortcut(app.app_handle(), activation_shortcut).unwrap();
|
|
67
68
|
|
|
68
69
|
// Show window after state restoration to prevent position flashing
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
70
|
+
// Unless start_to_tray is enabled, then keep it hidden
|
|
71
|
+
if !start_to_tray {
|
|
72
|
+
let window_clone = window.clone();
|
|
73
|
+
tauri::async_runtime::spawn(async move {
|
|
74
|
+
tokio::time::sleep(tokio::time::Duration::from_millis(50)).await;
|
|
75
|
+
window_clone.show().unwrap();
|
|
76
|
+
});
|
|
77
|
+
}
|
|
74
78
|
|
|
75
79
|
Ok(())
|
|
76
80
|
})
|