UNPKG

adaptorex

Version:

Connect all your live interactive storytelling devices and software

148 lines (121 loc) 4.81 kB
#!/usr/bin/env node // scripts/build-appimage.mjs // Packages the yao-pkg binary into a Linux AppImage. // Usage: node scripts/build-appimage.mjs [--arch x86_64|arm64] [--update-tool] const fs = require("fs") const path = require("path") const os = require("os") const { execSync, spawnSync } = require("child_process") const { createWriteStream } = require("fs") const { pipeline } = require("stream/promises") const { fileURLToPath } = require("url") const { version } = require("../package.json") function checkFileExists(p, label) { if (!fs.existsSync(p)) { console.error(`${label} not found: ${p}`) process.exit(1) } } async function main() { if (process.platform !== "linux") { console.error("AppImage builds are only supported on Linux.") process.exit(1) } const args = process.argv.slice(2) const ARCH = args.includes("--arch") ? args[args.indexOf("--arch") + 1] : "x86_64" const UPDATE_TOOL = args.includes("--update-tool") const BINARY_SRC = path.join("dist", `adaptorex-linux-${ARCH}`) // yao-pkg output const ICON_SRC = path.join(__dirname, "assets", "icon.png") const DESKTOP_SRC = path.join(__dirname, "assets", "adaptorex.desktop") const APPRUN_SRC = path.join(__dirname, "assets", "AppRun") const APP_DIR = path.join("dist", `adaptorex.AppDir`) const OUT_FILE = path.join("dist", `adaptorex-${version}-${ARCH}.AppImage`) const TOOL_ARCH = ARCH === "arm64" ? "aarch64" : ARCH const TOOL_CACHE = path.join(os.homedir(), ".cache", "appimagetool") const TOOL_PATH = path.join(TOOL_CACHE, `appimagetool-${TOOL_ARCH}.AppImage`) const TOOL_URL = `https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-${TOOL_ARCH}.AppImage` // Check if yao-pkg binary, icon file and .desktop exists console.log("Validating inputs") checkFileExists(BINARY_SRC, "pkg binary (run yao-pkg first)") checkFileExists(ICON_SRC, "Icon") checkFileExists(DESKTOP_SRC, ".desktop file") console.log(`app: adaptorex version: ${version} arch: ${ARCH}`) console.log("Building AppDir") // Clean previous build if (fs.existsSync(APP_DIR)) { fs.rmSync(APP_DIR, { recursive: true }) console.log("Removed existing AppDir") } // Make Directory structure const BIN_DIR = path.join(APP_DIR, "usr", "bin") fs.mkdirSync(BIN_DIR, { recursive: true }) // Copy Binary fs.copyFileSync(BINARY_SRC, path.join(BIN_DIR, "adaptorex")) fs.chmodSync(path.join(BIN_DIR, "adaptorex"), 0o755) console.log("Copied binary to usr/bin/") // Icon (root AND usr/share/icons for broader DE compatibility) const ICON_SHARE = path.join( APP_DIR, "usr", "share", "icons", "hicolor", "256x256", "apps" ) fs.mkdirSync(ICON_SHARE, { recursive: true }) fs.copyFileSync(ICON_SRC, path.join(APP_DIR, `adaptorex.png`)) fs.copyFileSync(ICON_SRC, path.join(ICON_SHARE, `adaptorex.png`)) console.log("Copied icon") // Copy .desktop file (root AND usr/share/applications) const DESKTOP_SHARE = path.join(APP_DIR, "usr", "share", "applications") fs.mkdirSync(DESKTOP_SHARE, { recursive: true }) fs.copyFileSync(DESKTOP_SRC, path.join(APP_DIR, `adaptorex.desktop`)) fs.copyFileSync(DESKTOP_SRC, path.join(DESKTOP_SHARE, `adaptorex.desktop`)) console.log("Copied .desktop") // Add AppRun script const appRunPath = path.join(APP_DIR, "AppRun") fs.copyFileSync(APPRUN_SRC, appRunPath) fs.chmodSync(appRunPath, 0o755) console.log("Copied AppRun") // Ensure appimagetool exists. Download if missing console.log("Checking appimagetool") if (!fs.existsSync(TOOL_PATH) || UPDATE_TOOL) { console.log( UPDATE_TOOL ? "Updating appimagetool…" : "Not cached — downloading…" ) console.log(`Downloading ${TOOL_URL}`) fs.mkdirSync(path.dirname(TOOL_PATH), { recursive: true }) const res = await fetch(TOOL_URL) if (!res.ok) console.error(`Download failed: HTTP ${res.status}`) await pipeline(res.body, createWriteStream(TOOL_PATH)) fs.chmodSync(TOOL_PATH, 0o755) console.log(`Saved to ${TOOL_PATH}`) } else { console.log(`Using cached appimagetool (pass --update-tool to refresh)`) } // Build AppImage console.log("Running appimagetool") fs.mkdirSync("dist", { recursive: true }) const result = spawnSync(TOOL_PATH, [APP_DIR, OUT_FILE], { stdio: "inherit", env: { ...process.env, ARCH: TOOL_ARCH, VERSION: version, APPIMAGE_EXTRACT_AND_RUN: "1" } }) if (result.status !== 0) { console.error("appimagetool exited with errors.") } const sizeBytes = fs.statSync(OUT_FILE).size const sizeMB = (sizeBytes / 1024 / 1024).toFixed(1) console.log(`AppImage ready: ${OUT_FILE} Size: ${sizeMB} MB`) } main().catch((err) => { console.error(err) process.exit(1) })