123 lines
4.4 KiB
JavaScript
123 lines
4.4 KiB
JavaScript
|
|
import {spawn} from "node:child_process"
|
||
|
|
import {cp, mkdir, mkdtemp, readFile, readdir, rm} from "node:fs/promises"
|
||
|
|
import {join, resolve} from "node:path"
|
||
|
|
import {fileURLToPath} from "node:url"
|
||
|
|
import sharp from "sharp"
|
||
|
|
import {loadEnv} from "vite"
|
||
|
|
|
||
|
|
const root = fileURLToPath(new URL("../", import.meta.url))
|
||
|
|
const [target, option, ...rest] = process.argv.slice(2)
|
||
|
|
const platforms = {linux: "--linux", windows: "--win", macos: "--mac"}
|
||
|
|
const env = {...process.env, ...loadEnv("production", root, "VITE_"), NODE_ENV: "production"}
|
||
|
|
|
||
|
|
const run = (command, args, options = {}) =>
|
||
|
|
new Promise((resolve, reject) => {
|
||
|
|
const child = spawn(command, args, {cwd: root, env, stdio: "inherit", ...options})
|
||
|
|
child.on("error", reject)
|
||
|
|
child.on("exit", (code, signal) => {
|
||
|
|
if (code === 0) resolve()
|
||
|
|
else reject(new Error(`${command} failed (${signal || code})`))
|
||
|
|
})
|
||
|
|
})
|
||
|
|
|
||
|
|
try {
|
||
|
|
if (!Object.hasOwn(platforms, target) || rest.length || (option && option !== "--dir")) {
|
||
|
|
throw new Error("Usage: node scripts/package-desktop.mjs linux|windows|macos [--dir]")
|
||
|
|
}
|
||
|
|
delete env.FLOTILLA_DESKTOP_DEV_URL
|
||
|
|
delete env.CAPACITOR_ELECTRON_DEV_SERVER_URL
|
||
|
|
env.CSC_IDENTITY_AUTO_DISCOVERY = "false"
|
||
|
|
|
||
|
|
let logo
|
||
|
|
if (env.VITE_PLATFORM_LOGO?.startsWith("https://")) {
|
||
|
|
const response = await fetch(env.VITE_PLATFORM_LOGO, {signal: AbortSignal.timeout(30_000)})
|
||
|
|
if (!response.ok || !response.headers.get("content-type")?.startsWith("image/")) {
|
||
|
|
throw new Error("VITE_PLATFORM_LOGO must return a successful image response")
|
||
|
|
}
|
||
|
|
logo = Buffer.from(await response.arrayBuffer())
|
||
|
|
} else {
|
||
|
|
logo = await readFile(resolve(root, env.VITE_PLATFORM_LOGO))
|
||
|
|
}
|
||
|
|
env.VITE_PLATFORM_LOGO = "static/desktop-logo.png"
|
||
|
|
await sharp(logo).resize(1024, 1024).png().toFile(join(root, env.VITE_PLATFORM_LOGO))
|
||
|
|
|
||
|
|
await run("bash", ["scripts/build-desktop.sh"])
|
||
|
|
await cp(join(root, env.VITE_PLATFORM_LOGO), join(root, "electron/generated/icon.png"))
|
||
|
|
await cp(join(root, "LICENSE"), join(root, "electron/generated/LICENSE"))
|
||
|
|
await run(
|
||
|
|
process.execPath,
|
||
|
|
[join(root, "node_modules/@capawesome/capacitor-electron/dist/cli/index.js"), "vendor"],
|
||
|
|
{cwd: join(root, "electron")},
|
||
|
|
)
|
||
|
|
|
||
|
|
const args = [platforms[target], ...(option ? [option] : [])]
|
||
|
|
if (target === "macos" && option === "--dir") {
|
||
|
|
// --dir replaces configured targets, including their architectures.
|
||
|
|
args.push("--x64", "--arm64")
|
||
|
|
}
|
||
|
|
if (target === "windows" && process.platform === "linux") {
|
||
|
|
const files = await readdir(join(root, "electron/vendor"), {recursive: true})
|
||
|
|
if (files.some(file => file.endsWith(".node"))) {
|
||
|
|
throw new Error(
|
||
|
|
"Native Electron addons require a Windows ABI rebuild before packaging on Windows",
|
||
|
|
)
|
||
|
|
}
|
||
|
|
await mkdir(join(root, "electron/dist"), {recursive: true})
|
||
|
|
const directory = await mkdtemp(join(root, "electron/dist/package-"))
|
||
|
|
try {
|
||
|
|
await cp(join(root, "package.json"), join(directory, "package.json"))
|
||
|
|
for (const file of [
|
||
|
|
"package.json",
|
||
|
|
"package-lock.json",
|
||
|
|
"electron-builder.config.mjs",
|
||
|
|
"build",
|
||
|
|
"app",
|
||
|
|
"generated",
|
||
|
|
"vendor",
|
||
|
|
]) {
|
||
|
|
await cp(join(root, "electron", file), join(directory, "electron", file), {recursive: true})
|
||
|
|
}
|
||
|
|
await run("docker", [
|
||
|
|
"run",
|
||
|
|
"--rm",
|
||
|
|
"--platform",
|
||
|
|
"linux/amd64",
|
||
|
|
"--volume",
|
||
|
|
`${directory}:/project:Z`,
|
||
|
|
"--workdir",
|
||
|
|
"/project/electron",
|
||
|
|
"--env",
|
||
|
|
"USE_SYSTEM_WINE=true",
|
||
|
|
"--env",
|
||
|
|
"CSC_IDENTITY_AUTO_DISCOVERY=false",
|
||
|
|
"electronuserland/builder@sha256:41ae540902461b6cbc988987db79547fcc10cda04d2a6c6367504f59d4b37c64",
|
||
|
|
"bash",
|
||
|
|
"-c",
|
||
|
|
'owner=$1; group=$2; shift 2; npm ci --ignore-scripts && npm run pack -- "$@"; result=$?; chown -R "$owner:$group" /project; exit "$result"',
|
||
|
|
"--",
|
||
|
|
String(process.getuid()),
|
||
|
|
String(process.getgid()),
|
||
|
|
...args,
|
||
|
|
])
|
||
|
|
await cp(join(directory, "electron/dist"), join(root, "electron/dist"), {recursive: true})
|
||
|
|
} finally {
|
||
|
|
await rm(directory, {recursive: true, force: true})
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
await run(
|
||
|
|
process.execPath,
|
||
|
|
[
|
||
|
|
"node_modules/electron-builder/cli.js",
|
||
|
|
"--config",
|
||
|
|
"electron-builder.config.mjs",
|
||
|
|
"--publish",
|
||
|
|
"never",
|
||
|
|
...args,
|
||
|
|
],
|
||
|
|
{cwd: join(root, "electron")},
|
||
|
|
)
|
||
|
|
}
|
||
|
|
} finally {
|
||
|
|
await rm(join(root, "static/desktop-logo.png"), {force: true})
|
||
|
|
}
|