sudo-prompt-x 10.0.0-beta.1

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/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Joran Dirk Greef
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md ADDED
@@ -0,0 +1,146 @@
1
+ # sudo-prompt-x
2
+
3
+ [![npm version][npm-version-src]][npm-version-href]
4
+ [![npm downloads][npm-downloads-src]][npm-downloads-href]
5
+
6
+ Run a non-graphical terminal command using `sudo`, prompting the user with a graphical OS dialog if necessary. Useful for background Node.js applications or native Electron apps that need sudo privileges.
7
+
8
+ > [!NOTE]
9
+ > This is a modernized fork of [@vscode/sudo-prompt](https://github.com/bpasero/sudo-prompt), which itself is a fork of the original [sudo-prompt](https://github.com/jorangreef/sudo-prompt). Rewritten in TypeScript with Promise support, it remains a drop-in replacement for either package.
10
+
11
+ ## Features
12
+
13
+ - 🖥️ Cross-platform support
14
+ - macOS (native dialog via AppleScript)
15
+ - Linux (pkexec / kdesudo)
16
+ - Windows (UAC elevation)
17
+ - WSL (Windows Subsystem for Linux)
18
+ - 📝 Full TypeScript support
19
+ - 🚀 Native ESM & CommonJS compatibility
20
+ - ✨ Promise API with backwards-compatible callbacks
21
+ - 🛑 AbortSignal support for cancellation
22
+ - 📦 Direct platform imports for tree-shaking
23
+
24
+ ## Installation
25
+
26
+ ```bash
27
+ npm install sudo-prompt-x
28
+ ```
29
+
30
+ ## Usage
31
+
32
+ ```ts
33
+ import { exec } from 'sudo-prompt-x'
34
+
35
+ // Promise API (recommended)
36
+ const { stdout, stderr } = await exec('echo hello', { name: 'My App' })
37
+ console.log('stdout:', stdout)
38
+
39
+ // Callback API (backwards compatible)
40
+ exec('echo hello', { name: 'My App' }, (error, stdout, stderr) => {
41
+ if (error) throw error
42
+ console.log('stdout:', stdout)
43
+ })
44
+ ```
45
+
46
+ > [!NOTE]
47
+ > Your command should not start with the `sudo` prefix.
48
+
49
+ ## Options
50
+
51
+ ```ts
52
+ interface ExecOptions {
53
+ name?: string // App name shown in dialog (defaults to process.title)
54
+ icns?: string // Path to .icns icon (macOS only)
55
+ env?: Record<string, string> // Environment variables
56
+ cwd?: string // Working directory (defaults to process.cwd())
57
+ signal?: AbortSignal // AbortSignal for cancellation
58
+ }
59
+ ```
60
+
61
+ - `name` must be alphanumeric only (spaces allowed), max 128 characters
62
+ - Current working directory is preserved on all platforms
63
+ - Environment variables can be set via `options.env`
64
+ - Use `signal` to cancel long-running elevated commands
65
+
66
+ ## Screenshots
67
+
68
+ | macOS | Linux | Windows |
69
+ |-------|-------|---------|
70
+ | ![macOS](https://raw.githubusercontent.com/jorangreef/sudo-prompt/master/macos.png) | ![Linux](https://raw.githubusercontent.com/jorangreef/sudo-prompt/master/linux.png) | ![Windows](https://raw.githubusercontent.com/jorangreef/sudo-prompt/master/windows.png) |
71
+
72
+ ## Direct Platform Imports
73
+
74
+ For smaller bundles, you can import platform-specific implementations directly:
75
+
76
+ ```ts
77
+ // Only include Windows code
78
+ import { exec } from 'sudo-prompt-x/windows'
79
+
80
+ // Only include macOS code
81
+ import { exec } from 'sudo-prompt-x/mac'
82
+
83
+ // Only include Linux code
84
+ import { exec } from 'sudo-prompt-x/linux'
85
+
86
+ // WSL (runs Windows UAC from within WSL)
87
+ import { exec } from 'sudo-prompt-x/wsl'
88
+ ```
89
+
90
+ ## Platform Behavior
91
+
92
+ ### macOS
93
+
94
+ `sudo-prompt` should behave just like the `sudo` command in the shell. If your command does not work with the `sudo` command in the shell (perhaps because it uses `>` redirection to a restricted file), then it may not work with `sudo-prompt`. However, it is still possible to use `sudo-prompt` to get a privileged shell, [see this discussion for more information](https://github.com/jorangreef/sudo-prompt/issues/1).
95
+
96
+ ### Linux
97
+
98
+ `sudo-prompt` will use either `pkexec` or `kdesudo` to show the password prompt and run your command. Where possible, `sudo-prompt` will try to mimic `sudo`. Depending on which binary is used, and due to the limitations of some binaries, the name of your program or the command itself may be displayed to your user.
99
+
100
+ `sudo-prompt` will not use `gksudo` since `gksudo` does not support concurrent prompts. Passing `options.icns` is currently not supported on Linux. Patches are welcome to add support for icons based on `polkit`.
101
+
102
+ ### Windows
103
+
104
+ `sudo-prompt` will elevate your command using User Account Control (UAC). Passing `options.name` or `options.icns` is currently not supported on Windows.
105
+
106
+ ### WSL (Windows Subsystem for Linux)
107
+
108
+ When running inside WSL, use the `sudo-prompt-x/wsl` import to trigger Windows UAC elevation. This allows WSL applications to request administrator privileges through the Windows host. Paths are automatically translated between Linux and Windows formats.
109
+
110
+ ## Important Notes
111
+
112
+ ### Non-graphical commands only
113
+
114
+ Just as you should never use `sudo` to launch any graphical applications, you should never use `sudo-prompt` to launch any graphical applications. Doing so could cause files in your home directory to become owned by root. `sudo-prompt` is explicitly designed to launch non-graphical terminal commands. For more information, [read this post](http://www.psychocats.net/ubuntu/graphicalsudo).
115
+
116
+ ### Concurrency
117
+
118
+ On systems where the user has opted to have `tty-tickets` enabled (most systems), each call to `exec()` will result in a separate password prompt. Where `tty-tickets` are disabled, subsequent calls to `exec()` will still require a password prompt, even where the user's `sudo` timestamp file remains valid, due to edge cases with `sudo` itself, [see this discussion for more information](https://github.com/jorangreef/sudo-prompt/pull/76).
119
+
120
+ You should never rely on `sudo-prompt` to execute your calls in order. If you need to enforce ordering of calls, then you should explicitly order your calls in your application. Where your commands are short-lived, you should always queue your calls to `exec()` to make sure your user is not overloaded with password prompts.
121
+
122
+ ### Invalidating the timestamp
123
+
124
+ On macOS and Linux, you can invalidate the user's `sudo` timestamp file to force the prompt to appear by running the following command in your terminal:
125
+
126
+ ```sh
127
+ sudo -k
128
+ ```
129
+
130
+ ## Acknowledgments
131
+
132
+ This package is a fork of [@vscode/sudo-prompt](https://github.com/bpasero/sudo-prompt), which itself is a fork of the original [sudo-prompt](https://github.com/jorangreef/sudo-prompt). We would like to acknowledge the original authors:
133
+
134
+ - [Joran Dirk Greef](https://github.com/jorangreef) — original author
135
+ - [Benjamin Pasero](https://github.com/bpasero) — VS Code fork maintainer
136
+
137
+ ## License
138
+
139
+ [MIT](./LICENSE)
140
+
141
+ <!-- Badges -->
142
+
143
+ [npm-version-src]: https://img.shields.io/npm/v/sudo-prompt-x
144
+ [npm-version-href]: https://npmjs.com/package/sudo-prompt-x
145
+ [npm-downloads-src]: https://img.shields.io/npm/dm/sudo-prompt-x
146
+ [npm-downloads-href]: https://www.npmcharts.com/compare/sudo-prompt-x?interval=30
@@ -0,0 +1,4 @@
1
+ function escapeDoubleQuotes(e) {
2
+ return e.replace(/"/g, "\\\"");
3
+ }
4
+ export { escapeDoubleQuotes as t };
@@ -0,0 +1,9 @@
1
+ function escapeDoubleQuotes(e) {
2
+ return e.replace(/"/g, "\\\"");
3
+ }
4
+ Object.defineProperty(exports, "t", {
5
+ enumerable: !0,
6
+ get: function() {
7
+ return escapeDoubleQuotes;
8
+ }
9
+ });
@@ -0,0 +1,101 @@
1
+ let e = require("node:os");
2
+ let t = require("node:path");
3
+ let n = require("node:process");
4
+ function transformCommand(e) {
5
+ if (typeof e != "string") throw Error("Name must be a string.");
6
+ e = e.trim();
7
+ if (e.length === 0) throw Error("Command must not be empty.");
8
+ if (e.startsWith("sudo ")) throw Error("Command must not start with \"sudo\".");
9
+ return e;
10
+ }
11
+ function transformName(e) {
12
+ e ??= n.title;
13
+ if (typeof e != "string") throw Error("Name must be a string.");
14
+ e = e.trim();
15
+ if (e.length === 0) throw Error("Name must not be empty.");
16
+ if (e.length > 128) throw Error("Name must be 128 characters or fewer.");
17
+ if (!/^[a-z0-9 ]+$/i.test(e)) throw Error("Name must be alphanumeric (spaces are allowed).");
18
+ return e;
19
+ }
20
+ function transformMessage(e) {
21
+ if (!e) return e;
22
+ if (typeof e != "string") throw Error("Message must be a string.");
23
+ e = e.trim();
24
+ if (e.length > 256) throw Error("Message must be 256 characters or fewer.");
25
+ return e;
26
+ }
27
+ function transformEnvironmentVariables(e) {
28
+ if (!e) return e;
29
+ if (typeof e != "object") throw Error("Environment variables must be provided as an object.");
30
+ for (let t in e) {
31
+ let n = e[t];
32
+ if (typeof t != "string" || !/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(t)) throw Error(`Invalid environment variable name: ${JSON.stringify(t)}`);
33
+ if (typeof n != "string" || /[\r\n]/.test(n)) throw Error(`Invalid environment variable value: ${JSON.stringify(n)}`);
34
+ }
35
+ return e;
36
+ }
37
+ function transformOptions(r, i) {
38
+ i?.signal?.throwIfAborted();
39
+ i = { ...i };
40
+ r = transformCommand(r);
41
+ i.name = transformName(i.name);
42
+ i.message = transformMessage(i.message);
43
+ i.env = transformEnvironmentVariables(i.env);
44
+ i.tmpdir ??= (0, t.join)((0, e.tmpdir)(), crypto.randomUUID());
45
+ i.cwd ??= (0, n.cwd)();
46
+ return {
47
+ ...i,
48
+ command: r
49
+ };
50
+ }
51
+ function throwOrResult(e, { code: t, stdout: n, stderr: r }) {
52
+ if (t !== 0) {
53
+ let i = /* @__PURE__ */ Error(`Command failed: ${e}\n${r}`);
54
+ i.code = t;
55
+ i.cmd = e;
56
+ i.stdout = n;
57
+ i.stderr = r;
58
+ throw i;
59
+ }
60
+ return {
61
+ stdout: n,
62
+ stderr: r
63
+ };
64
+ }
65
+ const r = {
66
+ win32: () => Promise.resolve().then(() => require("./windows/index.cjs")),
67
+ darwin: () => Promise.resolve().then(() => require("./mac/index.cjs")),
68
+ linux: () => Promise.resolve().then(() => require("./linux/index.cjs"))
69
+ };
70
+ function inferImplementation() {
71
+ let e = r[n.platform];
72
+ if (!e) throw Error(`Platform ${JSON.stringify(n.platform)} is not supported.`);
73
+ return e();
74
+ }
75
+ async function exec(e, t, n) {
76
+ let { exec: r } = await inferImplementation();
77
+ let i = typeof t == "object";
78
+ if (!t || i && !n) return r(e, t);
79
+ let a = i ? t : void 0;
80
+ let o = i ? n : t;
81
+ if (typeof o != "function") throw Error("Callback must be a function.");
82
+ await r(e, a).then(({ stdout: e, stderr: t }) => o(void 0, e, t)).catch((e) => o(e, void 0, void 0));
83
+ }
84
+ Object.defineProperty(exports, "n", {
85
+ enumerable: !0,
86
+ get: function() {
87
+ return throwOrResult;
88
+ }
89
+ });
90
+ Object.defineProperty(exports, "r", {
91
+ enumerable: !0,
92
+ get: function() {
93
+ return transformOptions;
94
+ }
95
+ });
96
+ Object.defineProperty(exports, "t", {
97
+ enumerable: !0,
98
+ get: function() {
99
+ return exec;
100
+ }
101
+ });
@@ -0,0 +1,84 @@
1
+ import { tmpdir as e } from "node:os";
2
+ import { join as t } from "node:path";
3
+ import { cwd as n, platform as r, title as i } from "node:process";
4
+ function transformCommand(e) {
5
+ if (typeof e != "string") throw Error("Name must be a string.");
6
+ e = e.trim();
7
+ if (e.length === 0) throw Error("Command must not be empty.");
8
+ if (e.startsWith("sudo ")) throw Error("Command must not start with \"sudo\".");
9
+ return e;
10
+ }
11
+ function transformName(e) {
12
+ e ??= i;
13
+ if (typeof e != "string") throw Error("Name must be a string.");
14
+ e = e.trim();
15
+ if (e.length === 0) throw Error("Name must not be empty.");
16
+ if (e.length > 128) throw Error("Name must be 128 characters or fewer.");
17
+ if (!/^[a-z0-9 ]+$/i.test(e)) throw Error("Name must be alphanumeric (spaces are allowed).");
18
+ return e;
19
+ }
20
+ function transformMessage(e) {
21
+ if (!e) return e;
22
+ if (typeof e != "string") throw Error("Message must be a string.");
23
+ e = e.trim();
24
+ if (e.length > 256) throw Error("Message must be 256 characters or fewer.");
25
+ return e;
26
+ }
27
+ function transformEnvironmentVariables(e) {
28
+ if (!e) return e;
29
+ if (typeof e != "object") throw Error("Environment variables must be provided as an object.");
30
+ for (let t in e) {
31
+ let n = e[t];
32
+ if (typeof t != "string" || !/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(t)) throw Error(`Invalid environment variable name: ${JSON.stringify(t)}`);
33
+ if (typeof n != "string" || /[\r\n]/.test(n)) throw Error(`Invalid environment variable value: ${JSON.stringify(n)}`);
34
+ }
35
+ return e;
36
+ }
37
+ function transformOptions(r, i) {
38
+ i?.signal?.throwIfAborted();
39
+ i = { ...i };
40
+ r = transformCommand(r);
41
+ i.name = transformName(i.name);
42
+ i.message = transformMessage(i.message);
43
+ i.env = transformEnvironmentVariables(i.env);
44
+ i.tmpdir ??= t(e(), crypto.randomUUID());
45
+ i.cwd ??= n();
46
+ return {
47
+ ...i,
48
+ command: r
49
+ };
50
+ }
51
+ function throwOrResult(e, { code: t, stdout: n, stderr: r }) {
52
+ if (t !== 0) {
53
+ let i = /* @__PURE__ */ Error(`Command failed: ${e}\n${r}`);
54
+ i.code = t;
55
+ i.cmd = e;
56
+ i.stdout = n;
57
+ i.stderr = r;
58
+ throw i;
59
+ }
60
+ return {
61
+ stdout: n,
62
+ stderr: r
63
+ };
64
+ }
65
+ const a = {
66
+ win32: () => import("./windows/index.mjs"),
67
+ darwin: () => import("./mac/index.mjs"),
68
+ linux: () => import("./linux/index.mjs")
69
+ };
70
+ function inferImplementation() {
71
+ let e = a[r];
72
+ if (!e) throw Error(`Platform ${JSON.stringify(r)} is not supported.`);
73
+ return e();
74
+ }
75
+ async function exec(e, t, n) {
76
+ let { exec: r } = await inferImplementation();
77
+ let i = typeof t == "object";
78
+ if (!t || i && !n) return r(e, t);
79
+ let a = i ? t : void 0;
80
+ let o = i ? n : t;
81
+ if (typeof o != "function") throw Error("Callback must be a function.");
82
+ await r(e, a).then(({ stdout: e, stderr: t }) => o(void 0, e, t)).catch((e) => o(e, void 0, void 0));
83
+ }
84
+ export { throwOrResult as n, transformOptions as r, exec as t };
@@ -0,0 +1,40 @@
1
+ import { ExecException, ExecOptions as NodeExecOptions } from "node:child_process";
2
+
3
+ //#region src/platforms/mac/options.d.ts
4
+ interface ExecOptionsMac extends ExecOptionsBase {
5
+ /**
6
+ * @see https://en.wikipedia.org/wiki/Apple_Icon_Image_format
7
+ */
8
+ icns?: string;
9
+ }
10
+ //#endregion
11
+ //#region src/exec/options.d.ts
12
+ interface ExecOptionsBase extends Pick<NodeExecOptions, "cwd" | "env" | "signal"> {
13
+ name: string;
14
+ message?: string;
15
+ /**
16
+ * @default
17
+ * join(os.tmpdir(), crypto.randomUUID())
18
+ */
19
+ tmpdir: string;
20
+ }
21
+ type ExecOptionsPlatformSpecific = ExecOptionsMac;
22
+ interface ExecOptions extends ExecOptionsBase, ExecOptionsPlatformSpecific {}
23
+ //#endregion
24
+ //#region src/exec/result.d.ts
25
+ interface ExecResult {
26
+ stdout: string;
27
+ stderr: string;
28
+ }
29
+ //#endregion
30
+ //#region src/exec/index.d.ts
31
+ interface ExecCallback {
32
+ (error: undefined, stdout: string, stderr: string): void;
33
+ (error: ExecException, stdout: undefined, stderr: undefined): void;
34
+ }
35
+ declare function exec(command: string): Promise<ExecResult>;
36
+ declare function exec(command: string, options: ExecOptions): Promise<ExecResult>;
37
+ declare function exec(command: string, callback: ExecCallback): void;
38
+ declare function exec(command: string, options: ExecOptions, callback: ExecCallback): void;
39
+ //#endregion
40
+ export { ExecOptionsMac as a, ExecOptionsBase as i, ExecResult as n, ExecOptions as r, exec as t };
@@ -0,0 +1,40 @@
1
+ import { ExecException, ExecOptions as NodeExecOptions, exec, execFile } from "node:child_process";
2
+
3
+ //#region src/platforms/mac/options.d.ts
4
+ interface ExecOptionsMac extends ExecOptionsBase {
5
+ /**
6
+ * @see https://en.wikipedia.org/wiki/Apple_Icon_Image_format
7
+ */
8
+ icns?: string;
9
+ }
10
+ //#endregion
11
+ //#region src/exec/options.d.ts
12
+ interface ExecOptionsBase extends Pick<NodeExecOptions, "cwd" | "env" | "signal"> {
13
+ name: string;
14
+ message?: string;
15
+ /**
16
+ * @default
17
+ * join(os.tmpdir(), crypto.randomUUID())
18
+ */
19
+ tmpdir: string;
20
+ }
21
+ type ExecOptionsPlatformSpecific = ExecOptionsMac;
22
+ interface ExecOptions extends ExecOptionsBase, ExecOptionsPlatformSpecific {}
23
+ //#endregion
24
+ //#region src/exec/result.d.ts
25
+ interface ExecResult {
26
+ stdout: string;
27
+ stderr: string;
28
+ }
29
+ //#endregion
30
+ //#region src/exec/index.d.ts
31
+ interface ExecCallback {
32
+ (error: undefined, stdout: string, stderr: string): void;
33
+ (error: ExecException, stdout: undefined, stderr: undefined): void;
34
+ }
35
+ declare function exec$1(command: string): Promise<ExecResult>;
36
+ declare function exec$1(command: string, options: ExecOptions): Promise<ExecResult>;
37
+ declare function exec$1(command: string, callback: ExecCallback): void;
38
+ declare function exec$1(command: string, options: ExecOptions, callback: ExecCallback): void;
39
+ //#endregion
40
+ export { ExecOptionsMac as a, ExecOptionsBase as i, ExecResult as n, ExecOptions as r, exec$1 as t };
package/dist/index.cjs ADDED
@@ -0,0 +1,2 @@
1
+ const e = require("./exec-BjS_tGOr.cjs");
2
+ exports.exec = e.t;
@@ -0,0 +1,2 @@
1
+ import { r as ExecOptions, t as exec } from "./index-kvxLnCHI.cjs";
2
+ export { type ExecOptions, exec };
@@ -0,0 +1,2 @@
1
+ import { r as ExecOptions, t as exec } from "./index-vd1MVV7_.mjs";
2
+ export { type ExecOptions, exec };
package/dist/index.mjs ADDED
@@ -0,0 +1,2 @@
1
+ import { t as e } from "./exec-DzmncB7R.mjs";
2
+ export { e as exec };
@@ -0,0 +1,80 @@
1
+ const e = require("../exec-BjS_tGOr.cjs");
2
+ const t = require("../escape-CgAzXRKO.cjs");
3
+ const n = require("../node-D37hqdIB.cjs");
4
+ let r = require("node:fs/promises");
5
+ async function exec(r, i) {
6
+ let a = e.r(r, i);
7
+ let { command: o, env: s } = a;
8
+ let c = await firstAvailableRunner();
9
+ let l = crypto.randomUUID().replace(/-/g, "");
10
+ try {
11
+ let r = n.t(c.command({
12
+ ...a,
13
+ command: `/bin/bash -c "echo ${l}; ${t.t(o)}"`
14
+ }), {
15
+ maxBuffer: 134217728,
16
+ encoding: "utf-8",
17
+ env: s
18
+ });
19
+ let { stdout: i, stderr: u } = await r;
20
+ let d = {
21
+ code: r.child.exitCode ?? 0,
22
+ stdout: i.startsWith(l) ? i.slice(l.length) : i,
23
+ stderr: u
24
+ };
25
+ console.log(d);
26
+ return e.n(o, d);
27
+ } catch (t) {
28
+ let { code: n = 1, stdout: r = "", stderr: i = "" } = t;
29
+ let a = r.startsWith(l);
30
+ let s = {
31
+ code: n,
32
+ stdout: a ? r.slice(l.length) : r,
33
+ stderr: i
34
+ };
35
+ if (c.permissionDenied?.(s) || !a) throw Error("User did not grant permission.", { cause: t });
36
+ return e.n(o, s);
37
+ }
38
+ }
39
+ const i = {
40
+ kdesudo: {
41
+ pathname: "/usr/bin/kdesudo",
42
+ command({ name: e, message: n, command: r }) {
43
+ return [
44
+ this.pathname,
45
+ "--comment",
46
+ n ? `"${t.t(n)}"` : `"${t.t(e)} wants to make changes."`,
47
+ "-d",
48
+ "--",
49
+ r
50
+ ].join(" ");
51
+ }
52
+ },
53
+ pkexec: {
54
+ pathname: "/usr/bin/pkexec",
55
+ command({ command: e }) {
56
+ return [
57
+ this.pathname,
58
+ "--disable-internal-agent",
59
+ "--keep-cwd",
60
+ e
61
+ ].join(" ");
62
+ },
63
+ permissionDenied({ code: e }) {
64
+ return [126, 127].includes(e);
65
+ }
66
+ }
67
+ };
68
+ async function firstAvailableRunner() {
69
+ for (let e in i) {
70
+ let t = i[e];
71
+ try {
72
+ await (0, r.stat)(t.pathname);
73
+ return t;
74
+ } catch {
75
+ continue;
76
+ }
77
+ }
78
+ throw Error(`Unable to find one of: ${Object.values(i).map(({ pathname: e }) => e).join(", ")}.`);
79
+ }
80
+ exports.exec = exec;
@@ -0,0 +1,6 @@
1
+ import { n as ExecResult, r as ExecOptions } from "../index-kvxLnCHI.cjs";
2
+
3
+ //#region src/platforms/linux/index.d.ts
4
+ declare function exec(command: string, options?: ExecOptions): Promise<ExecResult>;
5
+ //#endregion
6
+ export { exec };
@@ -0,0 +1,6 @@
1
+ import { n as ExecResult, r as ExecOptions } from "../index-vd1MVV7_.mjs";
2
+
3
+ //#region src/platforms/linux/index.d.ts
4
+ declare function exec(command: string, options?: ExecOptions): Promise<ExecResult>;
5
+ //#endregion
6
+ export { exec };
@@ -0,0 +1,80 @@
1
+ import { n as e, r as t } from "../exec-DzmncB7R.mjs";
2
+ import { t as n } from "../escape-B_ZgkH4x.mjs";
3
+ import { t as r } from "../node-1fao-dnU.mjs";
4
+ import { stat as i } from "node:fs/promises";
5
+ async function exec(i, a) {
6
+ let o = t(i, a);
7
+ let { command: s, env: c } = o;
8
+ let l = await firstAvailableRunner();
9
+ let u = crypto.randomUUID().replace(/-/g, "");
10
+ try {
11
+ let t = r(l.command({
12
+ ...o,
13
+ command: `/bin/bash -c "echo ${u}; ${n(s)}"`
14
+ }), {
15
+ maxBuffer: 134217728,
16
+ encoding: "utf-8",
17
+ env: c
18
+ });
19
+ let { stdout: i, stderr: a } = await t;
20
+ let d = {
21
+ code: t.child.exitCode ?? 0,
22
+ stdout: i.startsWith(u) ? i.slice(u.length) : i,
23
+ stderr: a
24
+ };
25
+ console.log(d);
26
+ return e(s, d);
27
+ } catch (t) {
28
+ let { code: n = 1, stdout: r = "", stderr: i = "" } = t;
29
+ let a = r.startsWith(u);
30
+ let o = {
31
+ code: n,
32
+ stdout: a ? r.slice(u.length) : r,
33
+ stderr: i
34
+ };
35
+ if (l.permissionDenied?.(o) || !a) throw Error("User did not grant permission.", { cause: t });
36
+ return e(s, o);
37
+ }
38
+ }
39
+ const a = {
40
+ kdesudo: {
41
+ pathname: "/usr/bin/kdesudo",
42
+ command({ name: e, message: t, command: r }) {
43
+ return [
44
+ this.pathname,
45
+ "--comment",
46
+ t ? `"${n(t)}"` : `"${n(e)} wants to make changes."`,
47
+ "-d",
48
+ "--",
49
+ r
50
+ ].join(" ");
51
+ }
52
+ },
53
+ pkexec: {
54
+ pathname: "/usr/bin/pkexec",
55
+ command({ command: e }) {
56
+ return [
57
+ this.pathname,
58
+ "--disable-internal-agent",
59
+ "--keep-cwd",
60
+ e
61
+ ].join(" ");
62
+ },
63
+ permissionDenied({ code: e }) {
64
+ return [126, 127].includes(e);
65
+ }
66
+ }
67
+ };
68
+ async function firstAvailableRunner() {
69
+ for (let e in a) {
70
+ let t = a[e];
71
+ try {
72
+ await i(t.pathname);
73
+ return t;
74
+ } catch {
75
+ continue;
76
+ }
77
+ }
78
+ throw Error(`Unable to find one of: ${Object.values(a).map(({ pathname: e }) => e).join(", ")}.`);
79
+ }
80
+ export { exec };