electrobun 0.0.19-beta.75 → 0.0.19-beta.76
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 +1 -1
- package/src/cli/index.ts +73 -27
package/package.json
CHANGED
package/src/cli/index.ts
CHANGED
|
@@ -11,6 +11,8 @@ import {
|
|
|
11
11
|
readdirSync,
|
|
12
12
|
rmSync,
|
|
13
13
|
symlinkSync,
|
|
14
|
+
statSync,
|
|
15
|
+
copyFileSync,
|
|
14
16
|
} from "fs";
|
|
15
17
|
import { execSync } from "child_process";
|
|
16
18
|
import tar from "tar";
|
|
@@ -1504,8 +1506,8 @@ if (commandArg === "init") {
|
|
|
1504
1506
|
buildEnvironment
|
|
1505
1507
|
);
|
|
1506
1508
|
|
|
1507
|
-
// Wrap Windows
|
|
1508
|
-
const wrappedExePath = await
|
|
1509
|
+
// Wrap Windows installer files in zip for distribution
|
|
1510
|
+
const wrappedExePath = await wrapWindowsInstallerInZip(selfExtractingExePath, buildFolder);
|
|
1509
1511
|
artifactsToUpload.push(wrappedExePath);
|
|
1510
1512
|
|
|
1511
1513
|
// Also keep the raw exe for backwards compatibility (optional)
|
|
@@ -1878,7 +1880,7 @@ async function createWindowsSelfExtractingExe(
|
|
|
1878
1880
|
targetPaths: any,
|
|
1879
1881
|
buildEnvironment: string
|
|
1880
1882
|
): Promise<string> {
|
|
1881
|
-
console.log("Creating
|
|
1883
|
+
console.log("Creating Windows installer with separate archive...");
|
|
1882
1884
|
|
|
1883
1885
|
// Format: MyApp-Setup.exe (stable) or MyApp-Setup-canary.exe (non-stable)
|
|
1884
1886
|
const setupFileName = buildEnvironment === "stable"
|
|
@@ -1887,43 +1889,40 @@ async function createWindowsSelfExtractingExe(
|
|
|
1887
1889
|
|
|
1888
1890
|
const outputExePath = join(buildFolder, setupFileName);
|
|
1889
1891
|
|
|
1890
|
-
//
|
|
1892
|
+
// Copy the extractor exe
|
|
1891
1893
|
const extractorExe = readFileSync(targetPaths.EXTRACTOR);
|
|
1894
|
+
writeFileSync(outputExePath, extractorExe);
|
|
1892
1895
|
|
|
1893
|
-
//
|
|
1894
|
-
const compressedArchive = readFileSync(compressedTarPath);
|
|
1895
|
-
|
|
1896
|
-
// Create metadata JSON
|
|
1896
|
+
// Create metadata JSON file
|
|
1897
1897
|
const metadata = {
|
|
1898
1898
|
identifier: config.app.identifier,
|
|
1899
1899
|
name: config.app.name,
|
|
1900
1900
|
channel: buildEnvironment
|
|
1901
1901
|
};
|
|
1902
|
-
const metadataJson = JSON.stringify(metadata);
|
|
1903
|
-
const
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
const metadataMarker = Buffer.from('ELECTROBUN_METADATA_V1', 'utf8');
|
|
1907
|
-
const archiveMarker = Buffer.from('ELECTROBUN_ARCHIVE_V1', 'utf8');
|
|
1908
|
-
|
|
1909
|
-
// Combine extractor + metadata marker + metadata + archive marker + archive
|
|
1910
|
-
const combinedBuffer = Buffer.concat([
|
|
1911
|
-
extractorExe,
|
|
1912
|
-
metadataMarker,
|
|
1913
|
-
metadataBuffer,
|
|
1914
|
-
archiveMarker,
|
|
1915
|
-
compressedArchive
|
|
1916
|
-
]);
|
|
1902
|
+
const metadataJson = JSON.stringify(metadata, null, 2);
|
|
1903
|
+
const metadataFileName = setupFileName.replace('.exe', '.metadata.json');
|
|
1904
|
+
const metadataPath = join(buildFolder, metadataFileName);
|
|
1905
|
+
writeFileSync(metadataPath, metadataJson);
|
|
1917
1906
|
|
|
1918
|
-
//
|
|
1919
|
-
|
|
1907
|
+
// Copy the compressed archive with matching name
|
|
1908
|
+
const archiveFileName = setupFileName.replace('.exe', '.tar.zst');
|
|
1909
|
+
const archivePath = join(buildFolder, archiveFileName);
|
|
1910
|
+
copyFileSync(compressedTarPath, archivePath);
|
|
1920
1911
|
|
|
1921
|
-
// Make
|
|
1912
|
+
// Make the exe executable (though Windows doesn't need chmod)
|
|
1922
1913
|
if (OS !== 'win') {
|
|
1923
1914
|
execSync(`chmod +x ${escapePathForTerminal(outputExePath)}`);
|
|
1924
1915
|
}
|
|
1925
1916
|
|
|
1926
|
-
|
|
1917
|
+
const exeSize = statSync(outputExePath).size;
|
|
1918
|
+
const archiveSize = statSync(archivePath).size;
|
|
1919
|
+
const totalSize = exeSize + archiveSize;
|
|
1920
|
+
|
|
1921
|
+
console.log(`Created Windows installer:`);
|
|
1922
|
+
console.log(` - Extractor: ${outputExePath} (${(exeSize / 1024 / 1024).toFixed(2)} MB)`);
|
|
1923
|
+
console.log(` - Archive: ${archivePath} (${(archiveSize / 1024 / 1024).toFixed(2)} MB)`);
|
|
1924
|
+
console.log(` - Metadata: ${metadataPath}`);
|
|
1925
|
+
console.log(` - Total size: ${(totalSize / 1024 / 1024).toFixed(2)} MB`);
|
|
1927
1926
|
|
|
1928
1927
|
return outputExePath;
|
|
1929
1928
|
}
|
|
@@ -1983,6 +1982,53 @@ async function createLinuxSelfExtractingBinary(
|
|
|
1983
1982
|
return outputPath;
|
|
1984
1983
|
}
|
|
1985
1984
|
|
|
1985
|
+
async function wrapWindowsInstallerInZip(exePath: string, buildFolder: string): Promise<string> {
|
|
1986
|
+
const exeName = basename(exePath);
|
|
1987
|
+
const exeStem = exeName.replace('.exe', '');
|
|
1988
|
+
|
|
1989
|
+
// Derive the paths for metadata and archive files
|
|
1990
|
+
const metadataPath = join(buildFolder, `${exeStem}.metadata.json`);
|
|
1991
|
+
const archivePath = join(buildFolder, `${exeStem}.tar.zst`);
|
|
1992
|
+
const zipPath = join(buildFolder, `${exeStem}.zip`);
|
|
1993
|
+
|
|
1994
|
+
// Verify all files exist
|
|
1995
|
+
if (!existsSync(exePath)) {
|
|
1996
|
+
throw new Error(`Installer exe not found: ${exePath}`);
|
|
1997
|
+
}
|
|
1998
|
+
if (!existsSync(metadataPath)) {
|
|
1999
|
+
throw new Error(`Metadata file not found: ${metadataPath}`);
|
|
2000
|
+
}
|
|
2001
|
+
if (!existsSync(archivePath)) {
|
|
2002
|
+
throw new Error(`Archive file not found: ${archivePath}`);
|
|
2003
|
+
}
|
|
2004
|
+
|
|
2005
|
+
// Create zip archive
|
|
2006
|
+
const output = createWriteStream(zipPath);
|
|
2007
|
+
const archive = archiver('zip', {
|
|
2008
|
+
zlib: { level: 9 } // Maximum compression
|
|
2009
|
+
});
|
|
2010
|
+
|
|
2011
|
+
return new Promise((resolve, reject) => {
|
|
2012
|
+
output.on('close', () => {
|
|
2013
|
+
console.log(`Created Windows installer package: ${zipPath} (${(archive.pointer() / 1024 / 1024).toFixed(2)} MB)`);
|
|
2014
|
+
resolve(zipPath);
|
|
2015
|
+
});
|
|
2016
|
+
|
|
2017
|
+
archive.on('error', (err) => {
|
|
2018
|
+
reject(err);
|
|
2019
|
+
});
|
|
2020
|
+
|
|
2021
|
+
archive.pipe(output);
|
|
2022
|
+
|
|
2023
|
+
// Add all three files to the archive
|
|
2024
|
+
archive.file(exePath, { name: basename(exePath) });
|
|
2025
|
+
archive.file(metadataPath, { name: basename(metadataPath) });
|
|
2026
|
+
archive.file(archivePath, { name: basename(archivePath) });
|
|
2027
|
+
|
|
2028
|
+
archive.finalize();
|
|
2029
|
+
});
|
|
2030
|
+
}
|
|
2031
|
+
|
|
1986
2032
|
async function wrapInArchive(filePath: string, buildFolder: string, archiveType: 'tar.gz' | 'zip'): Promise<string> {
|
|
1987
2033
|
const fileName = basename(filePath);
|
|
1988
2034
|
const fileDir = dirname(filePath);
|