🐛 Fix linux and windows packaging issues
This commit is contained in:
31
bin/helpers/merge.ts
vendored
31
bin/helpers/merge.ts
vendored
@@ -139,7 +139,38 @@ export async function mergeConfig(
|
|||||||
|
|
||||||
// Processing targets are currently only open to Linux.
|
// Processing targets are currently only open to Linux.
|
||||||
if (platform === 'linux') {
|
if (platform === 'linux') {
|
||||||
|
// Remove hardcoded desktop files and regenerate with correct app name
|
||||||
delete tauriConf.bundle.linux.deb.files;
|
delete tauriConf.bundle.linux.deb.files;
|
||||||
|
|
||||||
|
// Generate correct desktop file configuration
|
||||||
|
const appNameLower = name.toLowerCase();
|
||||||
|
const identifier = `com.pake.${appNameLower}`;
|
||||||
|
const desktopFileName = `${identifier}.desktop`;
|
||||||
|
|
||||||
|
// Create desktop file content
|
||||||
|
const desktopContent = `[Desktop Entry]
|
||||||
|
Version=1.0
|
||||||
|
Type=Application
|
||||||
|
Name=${name}
|
||||||
|
Comment=${name}
|
||||||
|
Exec=${appNameLower}
|
||||||
|
Icon=${appNameLower}
|
||||||
|
Categories=Network;WebBrowser;
|
||||||
|
MimeType=text/html;text/xml;application/xhtml_xml;
|
||||||
|
StartupNotify=true
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Write desktop file to assets directory
|
||||||
|
const assetsDir = path.join(npmDirectory, 'src-tauri/assets');
|
||||||
|
const desktopFilePath = path.join(assetsDir, desktopFileName);
|
||||||
|
await fsExtra.ensureDir(assetsDir);
|
||||||
|
await fsExtra.writeFile(desktopFilePath, desktopContent);
|
||||||
|
|
||||||
|
// Set up desktop file in bundle configuration
|
||||||
|
tauriConf.bundle.linux.deb.files = {
|
||||||
|
[`/usr/share/applications/${desktopFileName}`]: `assets/${desktopFileName}`,
|
||||||
|
};
|
||||||
|
|
||||||
const validTargets = ['deb', 'appimage', 'rpm'];
|
const validTargets = ['deb', 'appimage', 'rpm'];
|
||||||
if (validTargets.includes(options.targets)) {
|
if (validTargets.includes(options.targets)) {
|
||||||
tauriConf.bundle.targets = [options.targets];
|
tauriConf.bundle.targets = [options.targets];
|
||||||
|
|||||||
68
bin/options/icon.ts
vendored
68
bin/options/icon.ts
vendored
@@ -119,11 +119,49 @@ export async function handleIcon(options: PakeAppOptions, url?: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logger.info('✼ No icon provided, using default icon.');
|
logger.info('✼ No icon provided, using default icon.');
|
||||||
const iconPath = IS_WIN
|
|
||||||
? 'src-tauri/png/icon_256.ico'
|
// For Windows, ensure we have proper fallback handling
|
||||||
: IS_LINUX
|
if (IS_WIN) {
|
||||||
? 'src-tauri/png/icon_512.png'
|
const defaultIcoPath = path.join(
|
||||||
: 'src-tauri/icons/icon.icns';
|
npmDirectory,
|
||||||
|
'src-tauri/png/icon_256.ico',
|
||||||
|
);
|
||||||
|
const defaultPngPath = path.join(
|
||||||
|
npmDirectory,
|
||||||
|
'src-tauri/png/icon_512.png',
|
||||||
|
);
|
||||||
|
|
||||||
|
// First try default ico
|
||||||
|
if (await fsExtra.pathExists(defaultIcoPath)) {
|
||||||
|
return defaultIcoPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If ico doesn't exist, try to convert from png
|
||||||
|
if (await fsExtra.pathExists(defaultPngPath)) {
|
||||||
|
logger.info('✼ Default ico not found, converting from png...');
|
||||||
|
try {
|
||||||
|
const convertedPath = await convertIconFormat(defaultPngPath, 'icon');
|
||||||
|
if (convertedPath && (await fsExtra.pathExists(convertedPath))) {
|
||||||
|
return convertedPath;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
logger.warn(`Failed to convert default png to ico: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last resort: return png path if it exists (Windows can handle png in some cases)
|
||||||
|
if (await fsExtra.pathExists(defaultPngPath)) {
|
||||||
|
logger.warn('✼ Using png as fallback for Windows (may cause issues).');
|
||||||
|
return defaultPngPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If nothing exists, let the error bubble up
|
||||||
|
throw new Error('No default icon found for Windows build');
|
||||||
|
}
|
||||||
|
|
||||||
|
const iconPath = IS_LINUX
|
||||||
|
? 'src-tauri/png/icon_512.png'
|
||||||
|
: 'src-tauri/icons/icon.icns';
|
||||||
return path.join(npmDirectory, iconPath);
|
return path.join(npmDirectory, iconPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,9 +209,18 @@ async function tryGetFavicon(
|
|||||||
|
|
||||||
const serviceUrls = generateIconServiceUrls(domain);
|
const serviceUrls = generateIconServiceUrls(domain);
|
||||||
|
|
||||||
|
// Use shorter timeout for CI environments
|
||||||
|
const isCI =
|
||||||
|
process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true';
|
||||||
|
const downloadTimeout = isCI ? 5000 : ICON_CONFIG.downloadTimeout;
|
||||||
|
|
||||||
for (const serviceUrl of serviceUrls) {
|
for (const serviceUrl of serviceUrls) {
|
||||||
try {
|
try {
|
||||||
const faviconPath = await downloadIcon(serviceUrl, false);
|
const faviconPath = await downloadIcon(
|
||||||
|
serviceUrl,
|
||||||
|
false,
|
||||||
|
downloadTimeout,
|
||||||
|
);
|
||||||
if (!faviconPath) continue;
|
if (!faviconPath) continue;
|
||||||
|
|
||||||
const convertedPath = await convertIconFormat(faviconPath, appName);
|
const convertedPath = await convertIconFormat(faviconPath, appName);
|
||||||
@@ -183,7 +230,11 @@ async function tryGetFavicon(
|
|||||||
);
|
);
|
||||||
return convertedPath;
|
return convertedPath;
|
||||||
}
|
}
|
||||||
} catch {
|
} catch (error) {
|
||||||
|
// Log specific errors in CI for debugging
|
||||||
|
if (isCI) {
|
||||||
|
logger.debug(`Icon service ${serviceUrl} failed: ${error.message}`);
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -202,11 +253,12 @@ async function tryGetFavicon(
|
|||||||
export async function downloadIcon(
|
export async function downloadIcon(
|
||||||
iconUrl: string,
|
iconUrl: string,
|
||||||
showSpinner = true,
|
showSpinner = true,
|
||||||
|
customTimeout?: number,
|
||||||
): Promise<string | null> {
|
): Promise<string | null> {
|
||||||
try {
|
try {
|
||||||
const response = await axios.get(iconUrl, {
|
const response = await axios.get(iconUrl, {
|
||||||
responseType: 'arraybuffer',
|
responseType: 'arraybuffer',
|
||||||
timeout: ICON_CONFIG.downloadTimeout,
|
timeout: customTimeout || ICON_CONFIG.downloadTimeout,
|
||||||
});
|
});
|
||||||
|
|
||||||
const iconData = response.data;
|
const iconData = response.data;
|
||||||
|
|||||||
78
dist/cli.js
vendored
78
dist/cli.js
vendored
@@ -531,7 +531,33 @@ async function mergeConfig(url, options, tauriConf) {
|
|||||||
tauriConf.pake.system_tray[currentPlatform] = showSystemTray;
|
tauriConf.pake.system_tray[currentPlatform] = showSystemTray;
|
||||||
// Processing targets are currently only open to Linux.
|
// Processing targets are currently only open to Linux.
|
||||||
if (platform === 'linux') {
|
if (platform === 'linux') {
|
||||||
|
// Remove hardcoded desktop files and regenerate with correct app name
|
||||||
delete tauriConf.bundle.linux.deb.files;
|
delete tauriConf.bundle.linux.deb.files;
|
||||||
|
// Generate correct desktop file configuration
|
||||||
|
const appNameLower = name.toLowerCase();
|
||||||
|
const identifier = `com.pake.${appNameLower}`;
|
||||||
|
const desktopFileName = `${identifier}.desktop`;
|
||||||
|
// Create desktop file content
|
||||||
|
const desktopContent = `[Desktop Entry]
|
||||||
|
Version=1.0
|
||||||
|
Type=Application
|
||||||
|
Name=${name}
|
||||||
|
Comment=${name}
|
||||||
|
Exec=${appNameLower}
|
||||||
|
Icon=${appNameLower}
|
||||||
|
Categories=Network;WebBrowser;
|
||||||
|
MimeType=text/html;text/xml;application/xhtml_xml;
|
||||||
|
StartupNotify=true
|
||||||
|
`;
|
||||||
|
// Write desktop file to assets directory
|
||||||
|
const assetsDir = path.join(npmDirectory, 'src-tauri/assets');
|
||||||
|
const desktopFilePath = path.join(assetsDir, desktopFileName);
|
||||||
|
await fsExtra.ensureDir(assetsDir);
|
||||||
|
await fsExtra.writeFile(desktopFilePath, desktopContent);
|
||||||
|
// Set up desktop file in bundle configuration
|
||||||
|
tauriConf.bundle.linux.deb.files = {
|
||||||
|
[`/usr/share/applications/${desktopFileName}`]: `assets/${desktopFileName}`
|
||||||
|
};
|
||||||
const validTargets = ['deb', 'appimage', 'rpm'];
|
const validTargets = ['deb', 'appimage', 'rpm'];
|
||||||
if (validTargets.includes(options.targets)) {
|
if (validTargets.includes(options.targets)) {
|
||||||
tauriConf.bundle.targets = [options.targets];
|
tauriConf.bundle.targets = [options.targets];
|
||||||
@@ -1014,11 +1040,38 @@ async function handleIcon(options, url) {
|
|||||||
return faviconPath;
|
return faviconPath;
|
||||||
}
|
}
|
||||||
logger.info('✼ No icon provided, using default icon.');
|
logger.info('✼ No icon provided, using default icon.');
|
||||||
const iconPath = IS_WIN
|
// For Windows, ensure we have proper fallback handling
|
||||||
? 'src-tauri/png/icon_256.ico'
|
if (IS_WIN) {
|
||||||
: IS_LINUX
|
const defaultIcoPath = path.join(npmDirectory, 'src-tauri/png/icon_256.ico');
|
||||||
? 'src-tauri/png/icon_512.png'
|
const defaultPngPath = path.join(npmDirectory, 'src-tauri/png/icon_512.png');
|
||||||
: 'src-tauri/icons/icon.icns';
|
// First try default ico
|
||||||
|
if (await fsExtra.pathExists(defaultIcoPath)) {
|
||||||
|
return defaultIcoPath;
|
||||||
|
}
|
||||||
|
// If ico doesn't exist, try to convert from png
|
||||||
|
if (await fsExtra.pathExists(defaultPngPath)) {
|
||||||
|
logger.info('✼ Default ico not found, converting from png...');
|
||||||
|
try {
|
||||||
|
const convertedPath = await convertIconFormat(defaultPngPath, 'icon');
|
||||||
|
if (convertedPath && await fsExtra.pathExists(convertedPath)) {
|
||||||
|
return convertedPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
logger.warn(`Failed to convert default png to ico: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Last resort: return png path if it exists (Windows can handle png in some cases)
|
||||||
|
if (await fsExtra.pathExists(defaultPngPath)) {
|
||||||
|
logger.warn('✼ Using png as fallback for Windows (may cause issues).');
|
||||||
|
return defaultPngPath;
|
||||||
|
}
|
||||||
|
// If nothing exists, let the error bubble up
|
||||||
|
throw new Error('No default icon found for Windows build');
|
||||||
|
}
|
||||||
|
const iconPath = IS_LINUX
|
||||||
|
? 'src-tauri/png/icon_512.png'
|
||||||
|
: 'src-tauri/icons/icon.icns';
|
||||||
return path.join(npmDirectory, iconPath);
|
return path.join(npmDirectory, iconPath);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@@ -1054,9 +1107,12 @@ async function tryGetFavicon(url, appName) {
|
|||||||
const domain = new URL(url).hostname;
|
const domain = new URL(url).hostname;
|
||||||
const spinner = getSpinner(`Fetching icon from ${domain}...`);
|
const spinner = getSpinner(`Fetching icon from ${domain}...`);
|
||||||
const serviceUrls = generateIconServiceUrls(domain);
|
const serviceUrls = generateIconServiceUrls(domain);
|
||||||
|
// Use shorter timeout for CI environments
|
||||||
|
const isCI = process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true';
|
||||||
|
const downloadTimeout = isCI ? 5000 : ICON_CONFIG.downloadTimeout;
|
||||||
for (const serviceUrl of serviceUrls) {
|
for (const serviceUrl of serviceUrls) {
|
||||||
try {
|
try {
|
||||||
const faviconPath = await downloadIcon(serviceUrl, false);
|
const faviconPath = await downloadIcon(serviceUrl, false, downloadTimeout);
|
||||||
if (!faviconPath)
|
if (!faviconPath)
|
||||||
continue;
|
continue;
|
||||||
const convertedPath = await convertIconFormat(faviconPath, appName);
|
const convertedPath = await convertIconFormat(faviconPath, appName);
|
||||||
@@ -1065,7 +1121,11 @@ async function tryGetFavicon(url, appName) {
|
|||||||
return convertedPath;
|
return convertedPath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch {
|
catch (error) {
|
||||||
|
// Log specific errors in CI for debugging
|
||||||
|
if (isCI) {
|
||||||
|
logger.debug(`Icon service ${serviceUrl} failed: ${error.message}`);
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1080,11 +1140,11 @@ async function tryGetFavicon(url, appName) {
|
|||||||
/**
|
/**
|
||||||
* Downloads icon from URL
|
* Downloads icon from URL
|
||||||
*/
|
*/
|
||||||
async function downloadIcon(iconUrl, showSpinner = true) {
|
async function downloadIcon(iconUrl, showSpinner = true, customTimeout) {
|
||||||
try {
|
try {
|
||||||
const response = await axios.get(iconUrl, {
|
const response = await axios.get(iconUrl, {
|
||||||
responseType: 'arraybuffer',
|
responseType: 'arraybuffer',
|
||||||
timeout: ICON_CONFIG.downloadTimeout,
|
timeout: customTimeout || ICON_CONFIG.downloadTimeout,
|
||||||
});
|
});
|
||||||
const iconData = response.data;
|
const iconData = response.data;
|
||||||
if (!iconData || iconData.byteLength < ICON_CONFIG.minFileSize)
|
if (!iconData || iconData.byteLength < ICON_CONFIG.minFileSize)
|
||||||
|
|||||||
31
script/build_with_pake_cli.js
vendored
31
script/build_with_pake_cli.js
vendored
@@ -30,7 +30,9 @@ const main = async () => {
|
|||||||
// Check if pake-cli directory exists
|
// Check if pake-cli directory exists
|
||||||
if (!fs.existsSync(cliPath)) {
|
if (!fs.existsSync(cliPath)) {
|
||||||
console.error("Error: pake-cli not found at", cliPath);
|
console.error("Error: pake-cli not found at", cliPath);
|
||||||
console.error("Please make sure pake-cli is installed: npm install pake-cli");
|
console.error(
|
||||||
|
"Please make sure pake-cli is installed: npm install pake-cli",
|
||||||
|
);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,17 +44,7 @@ const main = async () => {
|
|||||||
// Remove .pake directory to force fresh config generation
|
// Remove .pake directory to force fresh config generation
|
||||||
if (fs.existsSync(pakeDirPath)) {
|
if (fs.existsSync(pakeDirPath)) {
|
||||||
fs.rmSync(pakeDirPath, { recursive: true, force: true });
|
fs.rmSync(pakeDirPath, { recursive: true, force: true });
|
||||||
console.log("Cleaned previous .pake directory");
|
console.log("Cleaned previous .pake directory for fresh build");
|
||||||
}
|
|
||||||
|
|
||||||
// Fix hardcoded default config in npm package
|
|
||||||
const defaultConfigPath = path.join("src-tauri", "tauri.conf.json");
|
|
||||||
if (fs.existsSync(defaultConfigPath)) {
|
|
||||||
const defaultConfig = JSON.parse(fs.readFileSync(defaultConfigPath, 'utf8'));
|
|
||||||
defaultConfig.productName = process.env.NAME;
|
|
||||||
defaultConfig.identifier = `com.pake.${process.env.NAME.toLowerCase()}`;
|
|
||||||
fs.writeFileSync(defaultConfigPath, JSON.stringify(defaultConfig, null, 2));
|
|
||||||
console.log(`Fixed default config: productName -> ${process.env.NAME}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build CLI parameters
|
// Build CLI parameters
|
||||||
@@ -95,7 +87,7 @@ const main = async () => {
|
|||||||
params.push("--icon", process.env.ICON);
|
params.push("--icon", process.env.ICON);
|
||||||
} else {
|
} else {
|
||||||
console.log(
|
console.log(
|
||||||
"Won't use icon as ICON environment variable is not defined!",
|
"No icon provided, pake-cli will attempt to fetch favicon or use default",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,13 +103,20 @@ const main = async () => {
|
|||||||
fs.mkdirSync("output");
|
fs.mkdirSync("output");
|
||||||
}
|
}
|
||||||
|
|
||||||
// pake-cli outputs files to current directory with pattern: {name}.{extension}
|
// pake-cli outputs files to current directory with various naming patterns
|
||||||
const files = fs.readdirSync(".");
|
const files = fs.readdirSync(".");
|
||||||
const namePattern = new RegExp(`^${process.env.NAME}\\..*$`);
|
const appName = process.env.NAME;
|
||||||
|
const escapedAppName = appName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // Escape regex special chars
|
||||||
|
|
||||||
|
// Create comprehensive pattern for app files
|
||||||
|
const appFilePattern = new RegExp(
|
||||||
|
`^(${escapedAppName}|${escapedAppName.toLowerCase()})(_.*|\\..*)$`,
|
||||||
|
"i",
|
||||||
|
);
|
||||||
let foundFiles = false;
|
let foundFiles = false;
|
||||||
|
|
||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
if (namePattern.test(file)) {
|
if (appFilePattern.test(file)) {
|
||||||
const destPath = path.join("output", file);
|
const destPath = path.join("output", file);
|
||||||
fs.renameSync(file, destPath);
|
fs.renameSync(file, destPath);
|
||||||
console.log(`Moved: ${file} -> output/${file}`);
|
console.log(`Moved: ${file} -> output/${file}`);
|
||||||
|
|||||||
Reference in New Issue
Block a user