@downdraft/cli 0.3.1 → 0.4.0-alpha.0
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 +2 -2
- package/scripts/package-desktop.mjs +79 -6
- package/src/usage.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@downdraft/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0-alpha.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/knackstedt/downdraft.git",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"@aws-sdk/client-s3": "^3.700.0",
|
|
15
|
-
"@downdraft/engine": "^0.
|
|
15
|
+
"@downdraft/engine": "^0.4.0-alpha.0",
|
|
16
16
|
"eta": "^3.5.0",
|
|
17
17
|
"jimp": "^1.6.1",
|
|
18
18
|
"resedit": "3.1.0"
|
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
//
|
|
7
7
|
// --runtime=bun|node|deno JS host embedded in the package (default:
|
|
8
8
|
// package.json build.runtime, else bun)
|
|
9
|
-
// --format=<csv> dir | deb | appimage | flatpak
|
|
10
|
-
// package.json build.linux.target,
|
|
9
|
+
// --format=<csv> dir | deb | appimage | flatpak | rpm
|
|
10
|
+
// (default: package.json build.linux.target,
|
|
11
|
+
// else dir)
|
|
11
12
|
// --mode=dev|debug|prod bundle mode (default: prod)
|
|
12
13
|
// --product-name=<name> display name (default: pkg.productName)
|
|
13
14
|
// --product-version=<v> version (default: pkg.version)
|
|
@@ -49,7 +50,8 @@
|
|
|
49
50
|
// linux: { target: ["deb","AppImage","flatpak"], category, maintainer,
|
|
50
51
|
// synopsis, description, icon },
|
|
51
52
|
// deb: { section, priority, depends: [] },
|
|
52
|
-
// flatpak:{ runtime, runtimeVersion, sdk, finishArgs: [] }
|
|
53
|
+
// flatpak:{ runtime, runtimeVersion, sdk, finishArgs: [] },
|
|
54
|
+
// rpm: { license, release, depends: [] }
|
|
53
55
|
// }
|
|
54
56
|
//
|
|
55
57
|
// Formats:
|
|
@@ -58,6 +60,8 @@
|
|
|
58
60
|
// assembled with dpkg-deb
|
|
59
61
|
// appimage — AppDir + AppRun + appimagetool (downloaded+cached on demand)
|
|
60
62
|
// flatpak — generated manifest + flatpak-builder + build-bundle
|
|
63
|
+
// rpm — same payload layout as deb, assembled with rpmbuild from a
|
|
64
|
+
// generated .spec + tarball Source0
|
|
61
65
|
// ============================================================================
|
|
62
66
|
|
|
63
67
|
import { spawnSync } from "node:child_process";
|
|
@@ -82,7 +86,7 @@ const [entry, outdirArg] = positional;
|
|
|
82
86
|
|
|
83
87
|
if (!entry || !outdirArg) {
|
|
84
88
|
console.error(
|
|
85
|
-
"usage: bun package-desktop.mjs [--runtime=bun|node|deno] [--format=dir|deb|appimage|flatpak,...] " +
|
|
89
|
+
"usage: bun package-desktop.mjs [--runtime=bun|node|deno] [--format=dir|deb|appimage|flatpak|rpm,...] " +
|
|
86
90
|
"[--mode=...] [--product-name=] [--product-version=] [--app-id=] [--executable-name=] [--icon=] " +
|
|
87
91
|
"[--node-bin=] [--deno-bin=] [--mcp] <entry.ts> <outdir>");
|
|
88
92
|
process.exit(1);
|
|
@@ -101,10 +105,10 @@ if (!["bun", "node", "deno"].includes(runtime)) {
|
|
|
101
105
|
}
|
|
102
106
|
const formats = (flagValue("format") ?? (Array.isArray(linuxCfg.target) ? linuxCfg.target.join(",") : linuxCfg.target) ?? "dir")
|
|
103
107
|
.split(",").map((s) => s.trim().toLowerCase()).filter(Boolean);
|
|
104
|
-
const KNOWN_FORMATS = new Set(["dir", "deb", "appimage", "flatpak"]);
|
|
108
|
+
const KNOWN_FORMATS = new Set(["dir", "deb", "appimage", "flatpak", "rpm"]);
|
|
105
109
|
for (const f of formats.values()) {
|
|
106
110
|
if (!KNOWN_FORMATS.has(f)) {
|
|
107
|
-
console.error(`unknown --format "${f}" — expected dir, deb, appimage, or
|
|
111
|
+
console.error(`unknown --format "${f}" — expected dir, deb, appimage, flatpak, or rpm`);
|
|
108
112
|
process.exit(1);
|
|
109
113
|
}
|
|
110
114
|
}
|
|
@@ -924,6 +928,75 @@ if (formats.includes("flatpak")) {
|
|
|
924
928
|
artifacts.push(`flatpak ${out}`);
|
|
925
929
|
}
|
|
926
930
|
|
|
931
|
+
// ── Format: rpm ──
|
|
932
|
+
|
|
933
|
+
if (formats.includes("rpm")) {
|
|
934
|
+
const rpmCfg = build.rpm ?? {};
|
|
935
|
+
if (!runOut("sh", ["-c", "command -v rpmbuild"])) {
|
|
936
|
+
throw new Error("rpmbuild not installed — required for the rpm format (apt install rpm)");
|
|
937
|
+
}
|
|
938
|
+
const stage = mkdtempSync(join(tmpdir(), "dd-rpm-"));
|
|
939
|
+
const topdir = join(stage, "rpmbuild");
|
|
940
|
+
for (const d of ["BUILD", "RPMS", "SOURCES", "SPECS"]) {
|
|
941
|
+
mkdirSync(join(topdir, d), { recursive: true });
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
// rpm versions can't contain "-" — "~" is rpm's "sorts before" marker,
|
|
945
|
+
// so 1.2.3-beta.1 → 1.2.3~beta.1 still orders below the final release.
|
|
946
|
+
const rpmVersion = version.replace(/-/g, "~");
|
|
947
|
+
|
|
948
|
+
// Source0 tarball — %setup unpacks it into BUILD/payload and %install
|
|
949
|
+
// copies the staged appdir + packaging metadata into %{buildroot}.
|
|
950
|
+
const payload = join(stage, "payload");
|
|
951
|
+
mkdirSync(payload, { recursive: true });
|
|
952
|
+
cpSync(appdir, join(payload, "appdir"), { recursive: true, verbatimSymlinks: true });
|
|
953
|
+
writeFileSync(join(payload, `${appId}.desktop`), desktopFile());
|
|
954
|
+
writeFileSync(join(payload, `${appId}.metainfo.xml`), metainfoXml());
|
|
955
|
+
if (iconPath) await iconSet(join(payload, "hicolor"));
|
|
956
|
+
run("tar", ["-czf", join(topdir, "SOURCES", `${exeName}-${rpmVersion}.tar.gz`), "-C", stage, "payload"]);
|
|
957
|
+
|
|
958
|
+
const depends = (rpmCfg.depends ?? ["glibc", "libstdc++", "vulkan-loader"]).join(", ");
|
|
959
|
+
writeFileSync(join(topdir, "SPECS", `${exeName}.spec`),
|
|
960
|
+
`# ${productName} — generated by package-desktop.mjs\n` +
|
|
961
|
+
// A `bun build --compile` binary appends its embedded bundle past the
|
|
962
|
+
// ELF sections — brp-strip/__os_install_post would rewrite the file
|
|
963
|
+
// and silently drop it. AutoReqProv is off: the binary is self-
|
|
964
|
+
// contained, so only explicit Requires apply.
|
|
965
|
+
`%define debug_package %{nil}\n` +
|
|
966
|
+
`%global __os_install_post %{nil}\n` +
|
|
967
|
+
`AutoReqProv: no\n` +
|
|
968
|
+
`Name: ${exeName}\n` +
|
|
969
|
+
`Version: ${rpmVersion}\n` +
|
|
970
|
+
`Release: ${rpmCfg.release ?? "1%{?dist}"}\n` +
|
|
971
|
+
`Summary: ${synopsis}\n` +
|
|
972
|
+
`License: ${rpmCfg.license ?? "Proprietary"}\n` +
|
|
973
|
+
`Requires: ${depends}\n` +
|
|
974
|
+
`Source0: %{name}-%{version}.tar.gz\n` +
|
|
975
|
+
`\n%description\n${description}\n` +
|
|
976
|
+
`\n%prep\n%setup -q -n payload\n` +
|
|
977
|
+
`\n%build\n# prebuilt binary — nothing to compile\n` +
|
|
978
|
+
`\n%install\n` +
|
|
979
|
+
`mkdir -p %{buildroot}/usr/lib/%{name} %{buildroot}/usr/bin %{buildroot}%{_datadir}/applications %{buildroot}%{_datadir}/metainfo` +
|
|
980
|
+
(iconPath ? ` %{buildroot}%{_datadir}/icons\n` : "\n") +
|
|
981
|
+
`cp -a appdir/. %{buildroot}/usr/lib/%{name}/\n` +
|
|
982
|
+
`ln -s ../lib/%{name}/%{name} %{buildroot}/usr/bin/%{name}\n` +
|
|
983
|
+
`install -Dm644 ${appId}.desktop %{buildroot}%{_datadir}/applications/${appId}.desktop\n` +
|
|
984
|
+
`install -Dm644 ${appId}.metainfo.xml %{buildroot}%{_datadir}/metainfo/${appId}.metainfo.xml\n` +
|
|
985
|
+
(iconPath ? `cp -a hicolor %{buildroot}%{_datadir}/icons/\n` : "") +
|
|
986
|
+
`\n%files\n` +
|
|
987
|
+
`/usr/lib/%{name}\n` +
|
|
988
|
+
`/usr/bin/%{name}\n` +
|
|
989
|
+
`%{_datadir}/applications/${appId}.desktop\n` +
|
|
990
|
+
`%{_datadir}/metainfo/${appId}.metainfo.xml\n` +
|
|
991
|
+
(iconPath ? `%{_datadir}/icons/hicolor/*/apps/%{name}.png\n` : ""));
|
|
992
|
+
|
|
993
|
+
run("rpmbuild", ["-bb", "--define", `_topdir ${topdir}`, join(topdir, "SPECS", `${exeName}.spec`)]);
|
|
994
|
+
const built = readdirSync(join(topdir, "RPMS", "x86_64")).find((f) => f.endsWith(".rpm"));
|
|
995
|
+
const out = join(outdir, `${exeName}-${version}-linux-${runtime}.x86_64.rpm`);
|
|
996
|
+
copyFileSync(join(topdir, "RPMS", "x86_64", built), out);
|
|
997
|
+
artifacts.push(`rpm ${out}`);
|
|
998
|
+
}
|
|
999
|
+
|
|
927
1000
|
// ── koffi prebuild fetch (same mechanism as package-mobile) ──
|
|
928
1001
|
|
|
929
1002
|
async function fetchKoffiPrebuild(pkgName, ver) {
|
package/src/usage.ts
CHANGED
|
@@ -46,7 +46,7 @@ export const COMMANDS: CommandEntry[] = [
|
|
|
46
46
|
{ name: "game", alias: "g", type: "string", description: "Game to release (games/<game>). For multiple games, use --games. If omitted, infers from the current directory, or defaults to the only game in games/." },
|
|
47
47
|
{ name: "games", type: "string", description: "Comma-separated game names (e.g. sandjongg,to-the-ocean)" },
|
|
48
48
|
{ name: "target", alias: "t", type: "string", default: "all", enum: [...RELEASE_TARGETS], description: "Target platform(s): win, linux, mac, android, or all (android can't mix with desktop targets)" },
|
|
49
|
-
{ name: "format", type: "string", description: "Package format(s), comma-separated: dir, deb, appimage, flatpak (linux only; default: build.linux.target in package.json, else dir)" },
|
|
49
|
+
{ name: "format", type: "string", description: "Package format(s), comma-separated: dir, deb, appimage, flatpak, rpm (linux only; default: build.linux.target in package.json, else dir)" },
|
|
50
50
|
{ name: "runtime", type: "string", enum: ["bun", "node", "deno", "all"], description: "JS runtime embedded in the package: bun (compiled binary), node, deno, or all (default: build.runtime in package.json, \"runtime\" in downdraft.config.json, else bun). node/deno are linux-only today" },
|
|
51
51
|
{ name: "stage", type: "string", default: "release", enum: [...RELEASE_STAGES], description: "Stage: build, package, or release (all compile the native binary)" },
|
|
52
52
|
{ name: "mode", type: "string", default: "prod", enum: [...BUILD_MODES], description: "Build mode" },
|