@bobfrankston/msger 0.1.412 → 0.1.413
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/cli.js +7 -1
- package/msger-native/bin/msgernative-linux-aarch64 +0 -0
- package/msger-native/builder/postinstall.js +67 -18
- package/package.json +1 -1
- package/shower.d.ts +17 -0
- package/shower.js +76 -2
package/cli.js
CHANGED
|
@@ -3,9 +3,14 @@
|
|
|
3
3
|
* msger CLI - uses universal CLI from msgcommon
|
|
4
4
|
*/
|
|
5
5
|
import { runCli } from '@bobfrankston/msgcommon';
|
|
6
|
-
import { showMessageBox } from './shower.js';
|
|
6
|
+
import { showMessageBox, installLinuxDeps } from './shower.js';
|
|
7
7
|
import packageJson from './package.json' with { type: 'json' };
|
|
8
8
|
import path from 'path';
|
|
9
|
+
// Handled before runCli: this is a setup command, not a message box, and it
|
|
10
|
+
// has to work on a machine where msger cannot start at all.
|
|
11
|
+
if (process.argv.slice(2).some(a => a === '--install-deps' || a === '-install-deps')) {
|
|
12
|
+
process.exit(installLinuxDeps());
|
|
13
|
+
}
|
|
9
14
|
const HELP_TEXT = `
|
|
10
15
|
msger v${packageJson.version} - Fast, lightweight, cross-platform message box (Rust-powered)
|
|
11
16
|
|
|
@@ -23,6 +28,7 @@ Options:
|
|
|
23
28
|
-url <url|file|dir> Load URL directly in webview (no template, no buttons)
|
|
24
29
|
A local file or directory works too; a directory loads its index.html
|
|
25
30
|
-hash <fragment> Hash fragment to append to URL (requires -url). Leading # optional.
|
|
31
|
+
--install-deps Linux: install the WebKitGTK runtime msger needs (uses sudo)
|
|
26
32
|
-buttons <label...> Specify button labels (e.g., -buttons Yes No Cancel)
|
|
27
33
|
-ok Add OK button
|
|
28
34
|
-cancel Add Cancel button
|
|
Binary file
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import fs from "fs";
|
|
15
15
|
import path from "path";
|
|
16
|
+
import { spawnSync } from "child_process";
|
|
16
17
|
import { fileURLToPath } from "url";
|
|
17
18
|
|
|
18
19
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -202,33 +203,81 @@ if (!isWindows) {
|
|
|
202
203
|
}
|
|
203
204
|
}
|
|
204
205
|
|
|
205
|
-
// Step 5: Linux —
|
|
206
|
+
// Step 5: Linux — make sure the WebKitGTK runtime msger links against exists.
|
|
206
207
|
//
|
|
207
|
-
//
|
|
208
|
-
//
|
|
209
|
-
//
|
|
210
|
-
//
|
|
211
|
-
//
|
|
212
|
-
//
|
|
208
|
+
// msger renders with the SYSTEM webview (that's why it's 7 MB, not 300), so
|
|
209
|
+
// without WebKitGTK the binary cannot start at all — the loader fails with a
|
|
210
|
+
// bare "libwebkit2gtk-4.1.so.0: cannot open shared object file" and exit 127,
|
|
211
|
+
// which reads like a broken msger rather than a missing dependency (Bob
|
|
212
|
+
// 2026-07-31, fresh Pi 4 on a Lite image; a full desktop image already has it).
|
|
213
|
+
//
|
|
214
|
+
// Install it automatically ONLY when that can't hurt or hang:
|
|
215
|
+
// - we already have root (a global npm install on the Pi does) or passwordless
|
|
216
|
+
// sudo, so nothing escalates and nothing prompts;
|
|
217
|
+
// - apt-get is present (the scriptable front end);
|
|
218
|
+
// - MSGER_SKIP_DEPS isn't set.
|
|
219
|
+
// Anything else — unprivileged install, sudo that would ask for a password,
|
|
220
|
+
// unknown distro — falls back to telling the user. An npm script must never
|
|
221
|
+
// block on a password prompt: unattended installs would hang forever.
|
|
213
222
|
if (!isWindows && process.platform === "linux") {
|
|
214
223
|
const soNames = ["libwebkit2gtk-4.1.so.0", "libjavascriptcoregtk-4.1.so.0"];
|
|
215
224
|
const libDirs = [
|
|
216
225
|
"/usr/lib", "/usr/local/lib", "/lib",
|
|
217
226
|
`/usr/lib/${process.arch === "arm64" ? "aarch64" : "x86_64"}-linux-gnu`,
|
|
218
227
|
];
|
|
219
|
-
const
|
|
228
|
+
const haveWebkit = () => soNames.every(so =>
|
|
220
229
|
libDirs.some(dir => { try { return fs.existsSync(path.join(dir, so)); } catch { return false; } })
|
|
221
230
|
);
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
231
|
+
|
|
232
|
+
if (!haveWebkit()) {
|
|
233
|
+
const isRoot = typeof process.getuid === "function" && process.getuid() === 0;
|
|
234
|
+
const hasAptGet = fs.existsSync("/usr/bin/apt-get");
|
|
235
|
+
// `sudo -n true` succeeds only when sudo needs no password.
|
|
236
|
+
const sudoNoPassword = !isRoot && hasAptGet &&
|
|
237
|
+
spawnSync("sudo", ["-n", "true"], { stdio: "ignore" }).status === 0;
|
|
238
|
+
const canInstall = hasAptGet && (isRoot || sudoNoPassword) && process.env.MSGER_SKIP_DEPS !== "1";
|
|
239
|
+
|
|
240
|
+
if (canInstall) {
|
|
241
|
+
const prefix = isRoot ? [] : ["sudo", "-n"];
|
|
242
|
+
const args = [...prefix, "apt-get", "install", "-y", "libwebkit2gtk-4.1-0"];
|
|
243
|
+
console.log("");
|
|
244
|
+
console.log(" msger: WebKitGTK runtime missing — installing it now:");
|
|
245
|
+
console.log(` ${args.join(" ")}`);
|
|
246
|
+
const run = (a) => spawnSync(a[0], a.slice(1), {
|
|
247
|
+
stdio: "inherit",
|
|
248
|
+
// -y alone isn't enough; some packages still ask without this.
|
|
249
|
+
env: { ...process.env, DEBIAN_FRONTEND: "noninteractive" },
|
|
250
|
+
});
|
|
251
|
+
let res = run(args);
|
|
252
|
+
if (res.status !== 0) {
|
|
253
|
+
// Usual cause is a stale package index (404 on the .deb).
|
|
254
|
+
console.log(" msger: retrying after apt-get update…");
|
|
255
|
+
run([...prefix, "apt-get", "update"]);
|
|
256
|
+
res = run(args);
|
|
257
|
+
}
|
|
258
|
+
if (res.status === 0 && haveWebkit()) {
|
|
259
|
+
console.log(" msger: WebKitGTK installed — msger is ready to run.");
|
|
260
|
+
console.log("");
|
|
261
|
+
} else {
|
|
262
|
+
console.log("");
|
|
263
|
+
console.log(" msger: WARNING — automatic install of WebKitGTK failed.");
|
|
264
|
+
console.log(" Run this by hand, then msger will work:");
|
|
265
|
+
console.log("");
|
|
266
|
+
console.log(" sudo apt install libwebkit2gtk-4.1-0");
|
|
267
|
+
console.log("");
|
|
268
|
+
}
|
|
269
|
+
} else {
|
|
270
|
+
console.log("");
|
|
271
|
+
console.log(" msger: WARNING — the WebKitGTK runtime was not found.");
|
|
272
|
+
console.log(" msger renders with the system webview and cannot");
|
|
273
|
+
console.log(" start without it. Install it with:");
|
|
274
|
+
console.log("");
|
|
275
|
+
console.log(" sudo apt install libwebkit2gtk-4.1-0");
|
|
276
|
+
console.log(" or: msger --install-deps");
|
|
277
|
+
console.log("");
|
|
278
|
+
console.log(" (runtime only; -dev is needed just to build msger)");
|
|
279
|
+
console.log("");
|
|
280
|
+
}
|
|
232
281
|
}
|
|
233
282
|
}
|
|
234
283
|
|
package/package.json
CHANGED
package/shower.d.ts
CHANGED
|
@@ -95,6 +95,23 @@ export declare function setAppName(name: string): void;
|
|
|
95
95
|
* provision so Rust's window icon search picks it up. Per-call `icon` in
|
|
96
96
|
* `MessageBoxOptions` still takes precedence. */
|
|
97
97
|
export declare function setAppIcon(iconPath: string): void;
|
|
98
|
+
/** The right package for this distro. Only the runtime library — building
|
|
99
|
+
* msger additionally needs the -dev package, which is not msger's business to
|
|
100
|
+
* install on a machine that only runs it. */
|
|
101
|
+
export declare function webkitInstallCommand(): string;
|
|
102
|
+
/** `msger --install-deps` — install the WebKitGTK runtime msger links against.
|
|
103
|
+
*
|
|
104
|
+
* Deliberately NOT done from postinstall: an npm script that shells out to
|
|
105
|
+
* `sudo apt` escalates privilege behind the user's back, blocks forever on a
|
|
106
|
+
* password prompt in any non-interactive install (CI, containers, unattended
|
|
107
|
+
* provisioning), and guesses wrong on distros it doesn't know. postinstall
|
|
108
|
+
* detects and tells; installing stays an explicit, interactive choice.
|
|
109
|
+
*
|
|
110
|
+
* Returns the process exit code to use. */
|
|
111
|
+
export declare function installLinuxDeps(): number;
|
|
112
|
+
/** Is the WebKitGTK runtime msger links against present? Mirrors the check in
|
|
113
|
+
* msger-native/builder/postinstall.js — keep the two in step. */
|
|
114
|
+
export declare function hasWebkitRuntime(): boolean;
|
|
98
115
|
/**
|
|
99
116
|
* Show a message box dialog using native Rust implementation (extended version)
|
|
100
117
|
* @param options Message box configuration
|
package/shower.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { spawn, execFileSync } from 'child_process';
|
|
1
|
+
import { spawn, spawnSync, execFileSync } from 'child_process';
|
|
2
2
|
import { platform } from 'os';
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import { pathToFileURL } from 'url';
|
|
@@ -81,9 +81,83 @@ function missingWebkitHint(stderr) {
|
|
|
81
81
|
if (!/libwebkit2gtk|libjavascriptcoregtk/.test(stderr))
|
|
82
82
|
return '';
|
|
83
83
|
return '\n\nmsger needs the WebKitGTK runtime, which this system does not have.\n' +
|
|
84
|
-
|
|
84
|
+
` ${webkitInstallCommand()}\n` +
|
|
85
|
+
'or let msger run it for you:\n' +
|
|
86
|
+
' msger --install-deps\n' +
|
|
85
87
|
'(runtime only — the -dev package is needed just for building msger.)';
|
|
86
88
|
}
|
|
89
|
+
/** The right package for this distro. Only the runtime library — building
|
|
90
|
+
* msger additionally needs the -dev package, which is not msger's business to
|
|
91
|
+
* install on a machine that only runs it. */
|
|
92
|
+
export function webkitInstallCommand() {
|
|
93
|
+
const has = (cmd) => fs.existsSync(`/usr/bin/${cmd}`) || fs.existsSync(`/bin/${cmd}`);
|
|
94
|
+
if (has('apt'))
|
|
95
|
+
return 'sudo apt install libwebkit2gtk-4.1-0';
|
|
96
|
+
if (has('dnf'))
|
|
97
|
+
return 'sudo dnf install webkit2gtk4.1';
|
|
98
|
+
if (has('pacman'))
|
|
99
|
+
return 'sudo pacman -S webkit2gtk-4.1';
|
|
100
|
+
if (has('zypper'))
|
|
101
|
+
return 'sudo zypper install libwebkit2gtk-4_1-0';
|
|
102
|
+
return 'install the WebKitGTK 4.1 runtime for your distribution';
|
|
103
|
+
}
|
|
104
|
+
/** `msger --install-deps` — install the WebKitGTK runtime msger links against.
|
|
105
|
+
*
|
|
106
|
+
* Deliberately NOT done from postinstall: an npm script that shells out to
|
|
107
|
+
* `sudo apt` escalates privilege behind the user's back, blocks forever on a
|
|
108
|
+
* password prompt in any non-interactive install (CI, containers, unattended
|
|
109
|
+
* provisioning), and guesses wrong on distros it doesn't know. postinstall
|
|
110
|
+
* detects and tells; installing stays an explicit, interactive choice.
|
|
111
|
+
*
|
|
112
|
+
* Returns the process exit code to use. */
|
|
113
|
+
export function installLinuxDeps() {
|
|
114
|
+
if (platform() !== 'linux') {
|
|
115
|
+
console.error('--install-deps is for Linux; nothing to install on ' + platform());
|
|
116
|
+
return 1;
|
|
117
|
+
}
|
|
118
|
+
if (hasWebkitRuntime()) {
|
|
119
|
+
console.log('WebKitGTK runtime is already present — nothing to do.');
|
|
120
|
+
return 0;
|
|
121
|
+
}
|
|
122
|
+
const command = webkitInstallCommand();
|
|
123
|
+
if (!command.startsWith('sudo ')) {
|
|
124
|
+
console.error(`msger could not identify this distribution's package manager.\nPlease ${command}.`);
|
|
125
|
+
return 1;
|
|
126
|
+
}
|
|
127
|
+
console.log(`Running: ${command}`);
|
|
128
|
+
const [cmd, ...args] = command.split(' ');
|
|
129
|
+
// stdio inherit so sudo's password prompt actually reaches the terminal.
|
|
130
|
+
const res = spawnSync(cmd, args, { stdio: 'inherit' });
|
|
131
|
+
if (res.error) {
|
|
132
|
+
console.error(`Could not run ${cmd}: ${res.error.message}`);
|
|
133
|
+
return 1;
|
|
134
|
+
}
|
|
135
|
+
if (res.status !== 0)
|
|
136
|
+
return res.status ?? 1;
|
|
137
|
+
if (!hasWebkitRuntime()) {
|
|
138
|
+
console.error('Install reported success but the WebKitGTK runtime is still not visible.');
|
|
139
|
+
return 1;
|
|
140
|
+
}
|
|
141
|
+
console.log('WebKitGTK runtime installed — msger is ready to run.');
|
|
142
|
+
return 0;
|
|
143
|
+
}
|
|
144
|
+
/** Is the WebKitGTK runtime msger links against present? Mirrors the check in
|
|
145
|
+
* msger-native/builder/postinstall.js — keep the two in step. */
|
|
146
|
+
export function hasWebkitRuntime() {
|
|
147
|
+
if (platform() !== 'linux')
|
|
148
|
+
return true;
|
|
149
|
+
const soNames = ['libwebkit2gtk-4.1.so.0', 'libjavascriptcoregtk-4.1.so.0'];
|
|
150
|
+
const arch = process.arch === 'arm64' ? 'aarch64' : 'x86_64';
|
|
151
|
+
const libDirs = ['/usr/lib', '/usr/local/lib', '/lib', `/usr/lib/${arch}-linux-gnu`];
|
|
152
|
+
return soNames.every(so => libDirs.some(dir => {
|
|
153
|
+
try {
|
|
154
|
+
return fs.existsSync(path.join(dir, so));
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
}));
|
|
160
|
+
}
|
|
87
161
|
/** Raspberry Pi: WebKitGTK's DMABUF rendering path is broken on the vc4/v3d
|
|
88
162
|
* driver — the page comes up as interlaced shredded scanlines instead of
|
|
89
163
|
* content (verified on a Pi 5 / Debian 13 / WebKitGTK 2.50.6 Wayland session,
|