electrobun 0.0.19-beta.74 → 0.0.19-beta.75
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/package.json +3 -1
- package/src/cli/index.ts +84 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "electrobun",
|
|
3
|
-
"version": "0.0.19-beta.
|
|
3
|
+
"version": "0.0.19-beta.75",
|
|
4
4
|
"description": "Build ultra fast, tiny, and cross-platform desktop apps with Typescript.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Blackboard Technologies Inc.",
|
|
@@ -48,10 +48,12 @@
|
|
|
48
48
|
"build:push:artifacts": "bun scripts/build-and-upload-artifacts.js"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
+
"@types/archiver": "^6.0.3",
|
|
51
52
|
"@types/bun": "1.1.9"
|
|
52
53
|
},
|
|
53
54
|
"dependencies": {
|
|
54
55
|
"@oneidentity/zstd-js": "^1.0.3",
|
|
56
|
+
"archiver": "^7.0.1",
|
|
55
57
|
"rpc-anywhere": "1.5.0",
|
|
56
58
|
"tar": "^6.2.1"
|
|
57
59
|
}
|
package/src/cli/index.ts
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
} from "fs";
|
|
15
15
|
import { execSync } from "child_process";
|
|
16
16
|
import tar from "tar";
|
|
17
|
+
import archiver from "archiver";
|
|
17
18
|
import { ZstdInit } from "@oneidentity/zstd-js/wasm";
|
|
18
19
|
import { OS, ARCH } from '../shared/platform';
|
|
19
20
|
import { getTemplate, getTemplateNames } from './templates/embedded';
|
|
@@ -22,7 +23,7 @@ import { getTemplate, getTemplateNames } from './templates/embedded';
|
|
|
22
23
|
const MAX_CHUNK_SIZE = 1024 * 2;
|
|
23
24
|
|
|
24
25
|
|
|
25
|
-
const binExt = OS === 'win' ? '.exe' : '';
|
|
26
|
+
// const binExt = OS === 'win' ? '.exe' : '';
|
|
26
27
|
|
|
27
28
|
// this when run as an npm script this will be where the folder where package.json is.
|
|
28
29
|
const projectRoot = process.cwd();
|
|
@@ -611,6 +612,7 @@ const buildSubFolder = `${buildEnvironment}-${currentTarget.os}-${currentTarget.
|
|
|
611
612
|
// Use target OS/ARCH for build logic (instead of current machine's OS/ARCH)
|
|
612
613
|
const targetOS = currentTarget.os;
|
|
613
614
|
const targetARCH = currentTarget.arch;
|
|
615
|
+
const targetBinExt = targetOS === 'win' ? '.exe' : '';
|
|
614
616
|
|
|
615
617
|
const buildFolder = join(projectRoot, config.build.buildFolder, buildSubFolder);
|
|
616
618
|
|
|
@@ -846,7 +848,7 @@ if (commandArg === "init") {
|
|
|
846
848
|
// Only copy launcher for non-dev builds
|
|
847
849
|
if (buildEnvironment !== "dev") {
|
|
848
850
|
const bunCliLauncherBinarySource = targetPaths.LAUNCHER_RELEASE;
|
|
849
|
-
const bunCliLauncherDestination = join(appBundleMacOSPath, "launcher") +
|
|
851
|
+
const bunCliLauncherDestination = join(appBundleMacOSPath, "launcher") + targetBinExt;
|
|
850
852
|
const destLauncherFolder = dirname(bunCliLauncherDestination);
|
|
851
853
|
if (!existsSync(destLauncherFolder)) {
|
|
852
854
|
// console.info('creating folder: ', destFolder);
|
|
@@ -866,7 +868,7 @@ if (commandArg === "init") {
|
|
|
866
868
|
const bunBinarySourcePath = targetPaths.BUN_BINARY;
|
|
867
869
|
// Note: .bin/bun binary in node_modules is a symlink to the versioned one in another place
|
|
868
870
|
// in node_modules, so we have to dereference here to get the actual binary in the bundle.
|
|
869
|
-
const bunBinaryDestInBundlePath = join(appBundleMacOSPath, "bun") +
|
|
871
|
+
const bunBinaryDestInBundlePath = join(appBundleMacOSPath, "bun") + targetBinExt;
|
|
870
872
|
const destFolder2 = dirname(bunBinaryDestInBundlePath);
|
|
871
873
|
if (!existsSync(destFolder2)) {
|
|
872
874
|
// console.info('creating folder: ', destFolder);
|
|
@@ -1172,7 +1174,7 @@ if (commandArg === "init") {
|
|
|
1172
1174
|
|
|
1173
1175
|
// copy native bindings
|
|
1174
1176
|
const bsPatchSource = targetPaths.BSPATCH;
|
|
1175
|
-
const bsPatchDestination = join(appBundleMacOSPath, "bspatch") +
|
|
1177
|
+
const bsPatchDestination = join(appBundleMacOSPath, "bspatch") + targetBinExt;
|
|
1176
1178
|
const bsPatchDestFolder = dirname(bsPatchDestination);
|
|
1177
1179
|
if (!existsSync(bsPatchDestFolder)) {
|
|
1178
1180
|
mkdirSync(bsPatchDestFolder, { recursive: true });
|
|
@@ -1501,7 +1503,13 @@ if (commandArg === "init") {
|
|
|
1501
1503
|
targetPaths,
|
|
1502
1504
|
buildEnvironment
|
|
1503
1505
|
);
|
|
1504
|
-
|
|
1506
|
+
|
|
1507
|
+
// Wrap Windows exe in zip for native Windows support
|
|
1508
|
+
const wrappedExePath = await wrapInArchive(selfExtractingExePath, buildFolder, 'zip');
|
|
1509
|
+
artifactsToUpload.push(wrappedExePath);
|
|
1510
|
+
|
|
1511
|
+
// Also keep the raw exe for backwards compatibility (optional)
|
|
1512
|
+
// artifactsToUpload.push(selfExtractingExePath);
|
|
1505
1513
|
} else if (targetOS === 'linux') {
|
|
1506
1514
|
// Create desktop file for Linux
|
|
1507
1515
|
const desktopFileContent = `[Desktop Entry]
|
|
@@ -1554,7 +1562,13 @@ exec "\$LAUNCHER_BINARY" "\$@"
|
|
|
1554
1562
|
targetPaths,
|
|
1555
1563
|
buildEnvironment
|
|
1556
1564
|
);
|
|
1557
|
-
|
|
1565
|
+
|
|
1566
|
+
// Wrap Linux .run file in tar.gz to preserve permissions
|
|
1567
|
+
const wrappedRunPath = await wrapInArchive(selfExtractingLinuxPath, buildFolder, 'tar.gz');
|
|
1568
|
+
artifactsToUpload.push(wrappedRunPath);
|
|
1569
|
+
|
|
1570
|
+
// Also keep the raw .run for backwards compatibility (optional)
|
|
1571
|
+
// artifactsToUpload.push(selfExtractingLinuxPath);
|
|
1558
1572
|
|
|
1559
1573
|
// On Linux, create a tar.gz of the bundle
|
|
1560
1574
|
const linuxTarPath = join(buildFolder, `${appFileName}.tar.gz`);
|
|
@@ -1969,6 +1983,70 @@ async function createLinuxSelfExtractingBinary(
|
|
|
1969
1983
|
return outputPath;
|
|
1970
1984
|
}
|
|
1971
1985
|
|
|
1986
|
+
async function wrapInArchive(filePath: string, buildFolder: string, archiveType: 'tar.gz' | 'zip'): Promise<string> {
|
|
1987
|
+
const fileName = basename(filePath);
|
|
1988
|
+
const fileDir = dirname(filePath);
|
|
1989
|
+
|
|
1990
|
+
if (archiveType === 'tar.gz') {
|
|
1991
|
+
// Output filename: Setup.exe -> Setup.exe.tar.gz or Setup.run -> Setup.run.tar.gz
|
|
1992
|
+
const archivePath = filePath + '.tar.gz';
|
|
1993
|
+
|
|
1994
|
+
// For Linux files, ensure they have executable permissions before archiving
|
|
1995
|
+
if (fileName.endsWith('.run')) {
|
|
1996
|
+
try {
|
|
1997
|
+
// Try to set executable permissions (will only work on Unix-like systems)
|
|
1998
|
+
execSync(`chmod +x ${escapePathForTerminal(filePath)}`, { stdio: 'ignore' });
|
|
1999
|
+
} catch {
|
|
2000
|
+
// Ignore errors on Windows hosts
|
|
2001
|
+
}
|
|
2002
|
+
}
|
|
2003
|
+
|
|
2004
|
+
// Create tar.gz archive preserving permissions
|
|
2005
|
+
// Using the tar package for cross-platform compatibility
|
|
2006
|
+
await tar.c(
|
|
2007
|
+
{
|
|
2008
|
+
gzip: true,
|
|
2009
|
+
file: archivePath,
|
|
2010
|
+
cwd: fileDir,
|
|
2011
|
+
portable: true, // Ensures consistent behavior across platforms
|
|
2012
|
+
preservePaths: false,
|
|
2013
|
+
// The tar package should preserve file modes when creating archives
|
|
2014
|
+
},
|
|
2015
|
+
[fileName]
|
|
2016
|
+
);
|
|
2017
|
+
|
|
2018
|
+
console.log(`Created archive: ${archivePath} (preserving executable permissions)`);
|
|
2019
|
+
return archivePath;
|
|
2020
|
+
} else if (archiveType === 'zip') {
|
|
2021
|
+
// Output filename: Setup.exe -> Setup.zip
|
|
2022
|
+
const archivePath = filePath.replace(/\.[^.]+$/, '.zip');
|
|
2023
|
+
|
|
2024
|
+
// Create zip archive
|
|
2025
|
+
const output = createWriteStream(archivePath);
|
|
2026
|
+
const archive = archiver('zip', {
|
|
2027
|
+
zlib: { level: 9 } // Maximum compression
|
|
2028
|
+
});
|
|
2029
|
+
|
|
2030
|
+
return new Promise((resolve, reject) => {
|
|
2031
|
+
output.on('close', () => {
|
|
2032
|
+
console.log(`Created archive: ${archivePath} (${(archive.pointer() / 1024 / 1024).toFixed(2)} MB)`);
|
|
2033
|
+
resolve(archivePath);
|
|
2034
|
+
});
|
|
2035
|
+
|
|
2036
|
+
archive.on('error', (err) => {
|
|
2037
|
+
reject(err);
|
|
2038
|
+
});
|
|
2039
|
+
|
|
2040
|
+
archive.pipe(output);
|
|
2041
|
+
|
|
2042
|
+
// Add the file to the archive
|
|
2043
|
+
archive.file(filePath, { name: fileName });
|
|
2044
|
+
|
|
2045
|
+
archive.finalize();
|
|
2046
|
+
});
|
|
2047
|
+
}
|
|
2048
|
+
}
|
|
2049
|
+
|
|
1972
2050
|
async function createAppImage(buildFolder: string, appBundlePath: string, appFileName: string, config: any): Promise<string | null> {
|
|
1973
2051
|
try {
|
|
1974
2052
|
console.log("Creating AppImage...");
|