import { existsSync, mkdirSync, readdirSync, rmSync, statSync, } from "node:fs"; import path from "node:path"; import { spawnSync } from "node:child_process"; import { fileURLToPath } from "node:url"; const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); function findZstdDecompressCommand() { const systemZstd = spawnSync("zstd", ["--version"], { encoding: "utf8" }); if (systemZstd.status === 0) { return { command: "zstd", args: (inputPath, outputPath) => [ "-d", "-f", "-o", outputPath, inputPath, ] }; } const hostArch = process.arch === "arm64" ? "arm64" : "x64"; const candidates = [ path.join( rootDir, "node_modules/electrobun/dist-win-x64/zig-zstd", hostArch, "zig-zstd.exe", ), path.join( rootDir, "node_modules/electrobun/dist-win-x64/zig-zstd", "x64", "zig-zstd.exe", ), path.join(rootDir, "node_modules/electrobun/dist-win-x64", "zig-zstd"), ]; for (const candidate of candidates) { if (existsSync(candidate)) { return { command: candidate, args: (inputPath, outputPath) => [ "decompress", "-i", inputPath, "-o", outputPath, "--no-timing", ], }; } } return null; } function decompressTarZst(inputPath, outputPath) { const zstd = findZstdDecompressCommand(); if (!zstd) { throw new Error( "expand-windows-installer: zstd not found (install zstd or use electrobun dist binaries)", ); } const result = spawnSync(zstd.command, zstd.args(inputPath, outputPath), { stdio: "inherit", }); if (result.status !== 0) { throw new Error( `expand-windows-installer: decompression failed (exit ${result.status ?? 1})`, ); } } export function expandWindowsAppFromArchive(setupArchivePath, parentDir) { const resolvedArchive = path.resolve(setupArchivePath); if (!existsSync(resolvedArchive)) { throw new Error(`expand-windows-installer: archive not found: ${resolvedArchive}`); } const workDir = path.join(path.resolve(parentDir), ".expanded-app"); const tarPath = path.join(workDir, "app.tar"); rmSync(workDir, { recursive: true, force: true }); mkdirSync(workDir, { recursive: true }); decompressTarZst(resolvedArchive, tarPath); const extractTar = spawnSync("tar", ["-xf", tarPath, "-C", workDir], { stdio: "inherit", }); if (extractTar.status !== 0) { rmSync(workDir, { recursive: true, force: true }); throw new Error( `expand-windows-installer: tar extraction failed (exit ${extractTar.status ?? 1})`, ); } const appDir = readdirSync(workDir) .filter((entry) => entry !== "app.tar" && entry !== "__MACOSX") .map((entry) => path.join(workDir, entry)) .find((entryPath) => statSync(entryPath).isDirectory()); if (!appDir) { rmSync(workDir, { recursive: true, force: true }); throw new Error("expand-windows-installer: app folder not found in archive"); } console.log(`expand-windows-installer: expanded ${appDir}`); return appDir; } export function cleanExpandedWindowsApp(parentDir) { const workDir = path.join(path.resolve(parentDir), ".expanded-app"); rmSync(workDir, { recursive: true, force: true }); }