@tunnelbox/core 0.1.17 → 0.1.18
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/dist/index.js +50 -0
- package/package.json +1 -1
- package/src/cli.ts +63 -0
- package/src/index.ts +1 -0
package/dist/index.js
CHANGED
|
@@ -1804,6 +1804,52 @@ var MessagesCache = class {
|
|
|
1804
1804
|
}
|
|
1805
1805
|
};
|
|
1806
1806
|
var messagesCache = new MessagesCache();
|
|
1807
|
+
|
|
1808
|
+
// src/cli.ts
|
|
1809
|
+
import { spawnSync } from "child_process";
|
|
1810
|
+
import { existsSync as existsSync2 } from "fs";
|
|
1811
|
+
import { join as join2 } from "path";
|
|
1812
|
+
function needsCmdQuote(s) {
|
|
1813
|
+
return s === "" || /[ \t&|<>^"%]/.test(s);
|
|
1814
|
+
}
|
|
1815
|
+
function cmdLineFor(shimPath, args) {
|
|
1816
|
+
const parts = [`"${shimPath}"`, ...args.map((a) => needsCmdQuote(a) ? `"${a}"` : a)];
|
|
1817
|
+
return parts.join(" ");
|
|
1818
|
+
}
|
|
1819
|
+
function findWinShim(name) {
|
|
1820
|
+
if (name.includes("/") || name.includes("\\")) return null;
|
|
1821
|
+
const dirs = (process.env.PATH || "").split(";").filter(Boolean);
|
|
1822
|
+
for (const dir of dirs) {
|
|
1823
|
+
for (const ext of [".cmd", ".bat"]) {
|
|
1824
|
+
const p = join2(dir, name + ext);
|
|
1825
|
+
if (existsSync2(p)) return p;
|
|
1826
|
+
}
|
|
1827
|
+
}
|
|
1828
|
+
return null;
|
|
1829
|
+
}
|
|
1830
|
+
function killCliTree(child) {
|
|
1831
|
+
if (!child || child.exitCode !== null) return;
|
|
1832
|
+
if (process.platform === "win32") {
|
|
1833
|
+
const pid = child.pid;
|
|
1834
|
+
if (pid) {
|
|
1835
|
+
try {
|
|
1836
|
+
spawnSync("taskkill", ["/PID", String(pid), "/T", "/F"], { stdio: "ignore", windowsHide: true });
|
|
1837
|
+
} catch {
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
return;
|
|
1841
|
+
}
|
|
1842
|
+
try {
|
|
1843
|
+
child.kill("SIGTERM");
|
|
1844
|
+
} catch {
|
|
1845
|
+
}
|
|
1846
|
+
setTimeout(() => {
|
|
1847
|
+
try {
|
|
1848
|
+
if (child.exitCode === null) child.kill("SIGKILL");
|
|
1849
|
+
} catch {
|
|
1850
|
+
}
|
|
1851
|
+
}, 1500);
|
|
1852
|
+
}
|
|
1807
1853
|
export {
|
|
1808
1854
|
DEFAULT_LANG,
|
|
1809
1855
|
DEFAULT_PAGE_SIZE,
|
|
@@ -1815,12 +1861,16 @@ export {
|
|
|
1815
1861
|
RelayClient,
|
|
1816
1862
|
capMessage,
|
|
1817
1863
|
capMessages,
|
|
1864
|
+
cmdLineFor,
|
|
1818
1865
|
detectSystemLang,
|
|
1819
1866
|
envelope,
|
|
1867
|
+
findWinShim,
|
|
1820
1868
|
injectedRelayUrl,
|
|
1869
|
+
killCliTree,
|
|
1821
1870
|
loadState,
|
|
1822
1871
|
makeT,
|
|
1823
1872
|
messagesCache,
|
|
1873
|
+
needsCmdQuote,
|
|
1824
1874
|
normalizeLang,
|
|
1825
1875
|
printPairing,
|
|
1826
1876
|
renderPairingQrText,
|
package/package.json
CHANGED
package/src/cli.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI 子进程辅助:Windows `.cmd/.bat` shim 解析与进程树终止。
|
|
3
|
+
* 供各适配器驱动本机 CLI 时复用(Linux/macOS 直接 spawn 可执行文件)。
|
|
4
|
+
*/
|
|
5
|
+
import { spawnSync, type ChildProcess } from "node:child_process";
|
|
6
|
+
import { existsSync } from "node:fs";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
|
|
9
|
+
/** 参数是否需要 cmd 引号(含空格或 cmd 元字符)。 */
|
|
10
|
+
export function needsCmdQuote(s: string): boolean {
|
|
11
|
+
return s === "" || /[ \t&|<>^"%]/.test(s);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** 拼接一条 `cmd /c` 命令行:路径恒引号,参数按需引号。 */
|
|
15
|
+
export function cmdLineFor(shimPath: string, args: string[]): string {
|
|
16
|
+
const parts = [`"${shimPath}"`, ...args.map((a) => (needsCmdQuote(a) ? `"${a}"` : a))];
|
|
17
|
+
return parts.join(" ");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** 在 PATH 中查找 `<name>.cmd/.bat`(Windows shim);name 含路径分隔符时返回 null。 */
|
|
21
|
+
export function findWinShim(name: string): string | null {
|
|
22
|
+
if (name.includes("/") || name.includes("\\")) return null;
|
|
23
|
+
const dirs = (process.env.PATH || "").split(";").filter(Boolean);
|
|
24
|
+
for (const dir of dirs) {
|
|
25
|
+
for (const ext of [".cmd", ".bat"]) {
|
|
26
|
+
const p = join(dir, name + ext);
|
|
27
|
+
if (existsSync(p)) return p;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* 终止子进程:
|
|
35
|
+
* - Windows:`taskkill /PID <pid> /T /F` 杀整棵进程树(经 shell 启动时只杀 cmd.exe 不够);
|
|
36
|
+
* - 其余平台:SIGTERM,1.5s 后仍存活再 SIGKILL。
|
|
37
|
+
*/
|
|
38
|
+
export function killCliTree(child: ChildProcess | null | undefined): void {
|
|
39
|
+
if (!child || child.exitCode !== null) return;
|
|
40
|
+
if (process.platform === "win32") {
|
|
41
|
+
const pid = child.pid;
|
|
42
|
+
if (pid) {
|
|
43
|
+
try {
|
|
44
|
+
spawnSync("taskkill", ["/PID", String(pid), "/T", "/F"], { stdio: "ignore", windowsHide: true });
|
|
45
|
+
} catch {
|
|
46
|
+
/* ignore */
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
child.kill("SIGTERM");
|
|
53
|
+
} catch {
|
|
54
|
+
/* ignore */
|
|
55
|
+
}
|
|
56
|
+
setTimeout(() => {
|
|
57
|
+
try {
|
|
58
|
+
if (child.exitCode === null) child.kill("SIGKILL");
|
|
59
|
+
} catch {
|
|
60
|
+
/* ignore */
|
|
61
|
+
}
|
|
62
|
+
}, 1500);
|
|
63
|
+
}
|
package/src/index.ts
CHANGED