rdsh-gateway 0.8.0 → 0.8.2

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/service.d.ts CHANGED
@@ -21,8 +21,9 @@ export interface ServiceSpec {
21
21
  }
22
22
  /** systemd 用户级 unit 模板。 */
23
23
  export declare function systemdUnit(execStart: string, spec: ServiceSpec): string;
24
- /** launchd plist 模板。 */
25
- export declare function launchdPlist(execStart: string, spec: ServiceSpec): string;
24
+ /** launchd plist 模板。program 为启动前缀 argv([node, 脚本]),命令参数由 spec 提供——
25
+ * launchd 不做空格切分,每个 <string> 是一个 argv 元素,故 node 与脚本必须分开。 */
26
+ export declare function launchdPlist(program: string[], spec: ServiceSpec): string;
26
27
  /** 安装并启动服务(用户级)。 */
27
28
  export declare function installService(spec: ServiceSpec): Promise<string>;
28
29
  /** 服务状态。 */
package/dist/service.js CHANGED
@@ -58,9 +58,10 @@ RestartSec=3
58
58
  WantedBy=default.target
59
59
  `;
60
60
  }
61
- /** launchd plist 模板。 */
62
- export function launchdPlist(execStart, spec) {
63
- const args = commandArgs(spec).map((a) => ` <string>${a}</string>`).join("\n");
61
+ /** launchd plist 模板。program 为启动前缀 argv([node, 脚本]),命令参数由 spec 提供——
62
+ * launchd 不做空格切分,每个 <string> 是一个 argv 元素,故 node 与脚本必须分开。 */
63
+ export function launchdPlist(program, spec) {
64
+ const argLines = [...program, ...commandArgs(spec)].map((a) => ` <string>${a}</string>`).join("\n");
64
65
  const envBlock = spec.pathEnv !== undefined
65
66
  ? ` <key>EnvironmentVariables</key>
66
67
  <dict>
@@ -77,13 +78,15 @@ export function launchdPlist(execStart, spec) {
77
78
  <string>com.${spec.name}</string>
78
79
  <key>ProgramArguments</key>
79
80
  <array>
80
- <string>${execStart}</string>
81
- ${args}
81
+ ${argLines}
82
82
  </array>
83
83
  <key>RunAtLoad</key>
84
84
  <true/>
85
85
  <key>KeepAlive</key>
86
- <true/>
86
+ <dict>
87
+ <key>SuccessfulExit</key>
88
+ <false/>
89
+ </dict>
87
90
  ${envBlock} <key>StandardOutPath</key>
88
91
  <string>${serviceLogPath(spec.name)}</string>
89
92
  <key>StandardErrorPath</key>
@@ -103,18 +106,25 @@ async function run(cmd, args) {
103
106
  }
104
107
  /** 安装并启动服务(用户级)。 */
105
108
  export async function installService(spec) {
106
- const execStart = `${process.execPath} ${process.argv[1]}`;
109
+ const bin = process.argv[1];
110
+ if (bin === undefined) {
111
+ throw new Error("cannot install a service: the running entry script (process.argv[1]) is unknown");
112
+ }
107
113
  if (isLinux()) {
114
+ const execStart = `${process.execPath} ${bin}`;
108
115
  await mkdir(SYSTEMD_DIR, { recursive: true });
109
116
  await writeFile(systemdUnitPath(spec.name), systemdUnit(execStart, spec), { mode: 0o600 });
110
117
  await run("systemctl", ["--user", "daemon-reload"]);
111
118
  await run("systemctl", ["--user", "enable", "--now", spec.name]);
112
119
  return `installed systemd user unit: ${systemdUnitPath(spec.name)}`;
113
120
  }
121
+ // macOS(launchd):ProgramArguments 不做空格切分 —— node 与脚本必须作为独立 argv 元素
122
+ const plistPath = launchdPlistPath(spec.name);
114
123
  await mkdir(LAUNCHD_DIR, { recursive: true });
115
- await writeFile(launchdPlistPath(spec.name), launchdPlist(execStart, spec), { mode: 0o600 });
116
- await run("launchctl", ["load", launchdPlistPath(spec.name)]);
117
- return `installed launchd plist: ${launchdPlistPath(spec.name)}`;
124
+ await writeFile(plistPath, launchdPlist([process.execPath, bin], spec), { mode: 0o600 });
125
+ await run("launchctl", ["unload", plistPath]).catch(() => undefined); // 重装幂等:先卸旧 job(不存在时忽略)
126
+ await run("launchctl", ["load", plistPath]);
127
+ return `installed launchd plist: ${plistPath}`;
118
128
  }
119
129
  /** 服务状态。 */
120
130
  export async function serviceStatus(name = SERVICE_NAME) {
@@ -128,8 +138,9 @@ export async function serviceStatus(name = SERVICE_NAME) {
128
138
  }
129
139
  }
130
140
  try {
131
- await run("launchctl", ["print", `com.${name}`]);
132
- return "active";
141
+ const out = await run("launchctl", ["print", `com.${name}`]);
142
+ // loaded 但进程已退出的 job(如 exec 失败)print 仍成功 —— 按 state 细分
143
+ return out.includes("state = running") ? "active" : "loaded (not running)";
133
144
  }
134
145
  catch {
135
146
  return "unloaded";
@@ -40,9 +40,12 @@ export declare function compareDshVersions(a: string, b: string): number;
40
40
  /**
41
41
  * remote-dsh 已实测兼容的 dsh 版本窗口(registry 实存版本定界)。
42
42
  * ⚠️ 适配新的 dsh 版本并真机实测后,须同步扩展此窗口(见 doc/fix/20260907-dsh-0.1.2-rc1-auth/)。
43
+ * 2026-09-11:MAX 扩到 `0.1.5-rc.2` —— 真机实测通过(spawn + ready 行 token + 会话 cookie 换发 +
44
+ * `/api` 转发 + HTML 注入 + WS `/api/remote.mux` 桥接 + join 的 `patchLoopbackJs` 命中),
45
+ * 见 doc/review/20260911-dsh-0.1.5-rc.2-plugin-compat.md §5。
43
46
  */
44
47
  export declare const DSH_COMPAT_MIN = "0.1.1-rc.2";
45
- export declare const DSH_COMPAT_MAX = "0.1.2-rc.1";
48
+ export declare const DSH_COMPAT_MAX = "0.1.5-rc.2";
46
49
  /**
47
50
  * 版本落在实测窗口外时的提示文案(零文档导向:直接给动作指令,用户不查表)。
48
51
  * - 比 max 新 → 升级 remote-dsh 或暂用旧 dsh;
package/dist/spawn-dsh.js CHANGED
@@ -197,9 +197,12 @@ export function compareDshVersions(a, b) {
197
197
  /**
198
198
  * remote-dsh 已实测兼容的 dsh 版本窗口(registry 实存版本定界)。
199
199
  * ⚠️ 适配新的 dsh 版本并真机实测后,须同步扩展此窗口(见 doc/fix/20260907-dsh-0.1.2-rc1-auth/)。
200
+ * 2026-09-11:MAX 扩到 `0.1.5-rc.2` —— 真机实测通过(spawn + ready 行 token + 会话 cookie 换发 +
201
+ * `/api` 转发 + HTML 注入 + WS `/api/remote.mux` 桥接 + join 的 `patchLoopbackJs` 命中),
202
+ * 见 doc/review/20260911-dsh-0.1.5-rc.2-plugin-compat.md §5。
200
203
  */
201
204
  export const DSH_COMPAT_MIN = "0.1.1-rc.2";
202
- export const DSH_COMPAT_MAX = "0.1.2-rc.1";
205
+ export const DSH_COMPAT_MAX = "0.1.5-rc.2";
203
206
  /**
204
207
  * 版本落在实测窗口外时的提示文案(零文档导向:直接给动作指令,用户不查表)。
205
208
  * - 比 max 新 → 升级 remote-dsh 或暂用旧 dsh;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rdsh-gateway",
3
- "version": "0.8.0",
3
+ "version": "0.8.2",
4
4
  "description": "rdsh host-side component: LAN auth gateway + outbound tunnel endpoint (spawns dsh web)",
5
5
  "license": "MIT",
6
6
  "type": "module",