baton-host 0.1.4 → 0.1.6

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.
Files changed (2) hide show
  1. package/bin/baton-host.js +555 -24
  2. package/package.json +5 -5
package/bin/baton-host.js CHANGED
@@ -1,6 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- const { spawn } = require("node:child_process");
3
+ const { spawn, spawnSync } = require("node:child_process");
4
+ const fs = require("node:fs");
5
+ const os = require("node:os");
4
6
  const path = require("node:path");
5
7
 
6
8
  const mapping = {
@@ -10,37 +12,566 @@ const mapping = {
10
12
  "linux-x64": "baton-host-linux-x64"
11
13
  };
12
14
 
13
- const key = `${process.platform}-${process.arch}`;
14
- const pkg = mapping[key];
15
+ const SERVICE_LABEL = "com.baton.host";
16
+ const INSTALL_ROOT = path.join(os.homedir(), ".baton-host");
17
+ const INSTALL_BIN_DIR = path.join(INSTALL_ROOT, "bin");
18
+ const INSTALL_LOG_DIR = path.join(INSTALL_ROOT, "logs");
19
+ const ENV_FILE_PATH = path.join(INSTALL_ROOT, ".env");
20
+ const WRAPPER_PATH = path.join(INSTALL_ROOT, "run.sh");
21
+ const INSTALL_META_PATH = path.join(INSTALL_ROOT, "install.json");
15
22
 
16
- if (!pkg) {
17
- console.error(`❌ 当前平台暂不支持: ${key}`);
23
+ function fail(message) {
24
+ console.error(`❌ ${message}`);
18
25
  process.exit(1);
19
26
  }
20
27
 
21
- let binaryPath;
22
- try {
23
- const pkgJsonPath = require.resolve(`${pkg}/package.json`);
24
- binaryPath = path.join(path.dirname(pkgJsonPath), "bin", "baton-host");
25
- } catch (error) {
26
- console.error(`❌ 未找到平台二进制包 ${pkg},请重装 baton-host`);
27
- process.exit(1);
28
+ function getCurrentPlatformKey() {
29
+ return `${process.platform}-${process.arch}`;
30
+ }
31
+
32
+ function getMainPackageVersion() {
33
+ const packageJsonPath = path.join(__dirname, "..", "package.json");
34
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
35
+ return packageJson.version;
36
+ }
37
+
38
+ function resolveBundledAssets() {
39
+ const key = getCurrentPlatformKey();
40
+ const pkg = mapping[key];
41
+
42
+ if (!pkg) {
43
+ fail(`当前平台暂不支持: ${key}`);
44
+ }
45
+
46
+ let pkgJsonPath;
47
+ try {
48
+ pkgJsonPath = require.resolve(`${pkg}/package.json`);
49
+ } catch (error) {
50
+ fail(`未找到平台二进制包 ${pkg},请重新执行 npx baton-host@latest service install`);
51
+ }
52
+
53
+ const binaryPath = path.join(path.dirname(pkgJsonPath), "bin", "baton-host");
54
+ const cloudflaredPath = path.join(
55
+ path.dirname(binaryPath),
56
+ process.platform === "win32" ? "cloudflared.exe" : "cloudflared"
57
+ );
58
+
59
+ if (!fs.existsSync(binaryPath)) {
60
+ fail(`缺少 Baton Host 二进制: ${binaryPath}`);
61
+ }
62
+
63
+ if (!fs.existsSync(cloudflaredPath)) {
64
+ fail(`缺少 cloudflared 二进制: ${cloudflaredPath}`);
65
+ }
66
+
67
+ return {
68
+ binaryPath,
69
+ cloudflaredPath,
70
+ version: getMainPackageVersion()
71
+ };
28
72
  }
29
73
 
30
- const bundledCloudflaredPath = path.join(path.dirname(binaryPath), process.platform === "win32" ? "cloudflared.exe" : "cloudflared");
74
+ function ensureDir(dirPath) {
75
+ fs.mkdirSync(dirPath, { recursive: true });
76
+ }
77
+
78
+ function copyExecutable(sourcePath, targetPath) {
79
+ fs.copyFileSync(sourcePath, targetPath);
80
+ fs.chmodSync(targetPath, 0o755);
81
+ }
31
82
 
32
- const child = spawn(binaryPath, process.argv.slice(2), {
33
- stdio: "inherit",
34
- env: {
35
- ...process.env,
36
- BATON_CLOUDFLARED_BIN: bundledCloudflaredPath
83
+ function readInstallMeta() {
84
+ if (!fs.existsSync(INSTALL_META_PATH)) {
85
+ return null;
37
86
  }
38
- });
39
87
 
40
- child.on("exit", (code, signal) => {
41
- if (signal) {
42
- process.kill(process.pid, signal);
88
+ try {
89
+ return JSON.parse(fs.readFileSync(INSTALL_META_PATH, "utf8"));
90
+ } catch {
91
+ return null;
92
+ }
93
+ }
94
+
95
+ function writeInstallMeta(version) {
96
+ const payload = {
97
+ version,
98
+ installedAt: new Date().toISOString(),
99
+ platform: process.platform,
100
+ arch: process.arch
101
+ };
102
+ fs.writeFileSync(INSTALL_META_PATH, `${JSON.stringify(payload, null, 2)}\n`, "utf8");
103
+ }
104
+
105
+ function ensureDefaultEnvFile() {
106
+ if (fs.existsSync(ENV_FILE_PATH)) {
43
107
  return;
44
108
  }
45
- process.exit(code ?? 0);
46
- });
109
+
110
+ const defaultContent = [
111
+ "# Baton Host 服务环境变量",
112
+ "BATON_BRIDGE_MODE=lan",
113
+ "BRIDGE_LOG_PROFILE=core",
114
+ "PORT=9966",
115
+ ""
116
+ ].join("\n");
117
+
118
+ fs.writeFileSync(ENV_FILE_PATH, defaultContent, "utf8");
119
+ }
120
+
121
+ function readEnvFile() {
122
+ if (!fs.existsSync(ENV_FILE_PATH)) {
123
+ return {};
124
+ }
125
+
126
+ const result = {};
127
+ const content = fs.readFileSync(ENV_FILE_PATH, "utf8");
128
+ for (const rawLine of content.split(/\r?\n/)) {
129
+ const line = rawLine.trim();
130
+ if (!line || line.startsWith("#")) {
131
+ continue;
132
+ }
133
+ const separatorIndex = line.indexOf("=");
134
+ if (separatorIndex <= 0) {
135
+ continue;
136
+ }
137
+ const key = line.slice(0, separatorIndex).trim();
138
+ const value = line.slice(separatorIndex + 1).trim();
139
+ result[key] = value;
140
+ }
141
+ return result;
142
+ }
143
+
144
+ function buildWrapperScript() {
145
+ return `#!/bin/sh
146
+ set -eu
147
+
148
+ BATON_HOME="$HOME/.baton-host"
149
+ ENV_FILE="$BATON_HOME/.env"
150
+
151
+ if [ -f "$ENV_FILE" ]; then
152
+ while IFS= read -r line || [ -n "$line" ]; do
153
+ case "$line" in
154
+ ''|'#'*) continue ;;
155
+ *=*)
156
+ key=\${line%%=*}
157
+ value=\${line#*=}
158
+ export "$key=$value"
159
+ ;;
160
+ esac
161
+ done < "$ENV_FILE"
162
+ fi
163
+
164
+ export BATON_CLOUDFLARED_BIN="$BATON_HOME/bin/cloudflared"
165
+ export PATH="$HOME/.local/bin:$HOME/Library/pnpm:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin\${PATH:+:$PATH}"
166
+
167
+ exec "$BATON_HOME/bin/baton-host" "$@"
168
+ `;
169
+ }
170
+
171
+ function writeWrapperScript() {
172
+ fs.writeFileSync(WRAPPER_PATH, buildWrapperScript(), { mode: 0o755 });
173
+ fs.chmodSync(WRAPPER_PATH, 0o755);
174
+ }
175
+
176
+ function escapeXml(value) {
177
+ return String(value)
178
+ .replaceAll("&", "&amp;")
179
+ .replaceAll("<", "&lt;")
180
+ .replaceAll(">", "&gt;")
181
+ .replaceAll('"', "&quot;")
182
+ .replaceAll("'", "&apos;");
183
+ }
184
+
185
+ function getServicePathEnv() {
186
+ return `${os.homedir()}/.local/bin:${os.homedir()}/Library/pnpm:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin`;
187
+ }
188
+
189
+ function getLinuxServiceName() {
190
+ return `${SERVICE_LABEL}.service`;
191
+ }
192
+
193
+ function getLinuxUnitPath() {
194
+ return path.join(os.homedir(), ".config", "systemd", "user", getLinuxServiceName());
195
+ }
196
+
197
+ function buildLinuxUnit() {
198
+ return `[Unit]
199
+ Description=Baton Host
200
+ After=network-online.target
201
+ Wants=network-online.target
202
+
203
+ [Service]
204
+ Type=simple
205
+ ExecStart=%h/.baton-host/run.sh
206
+ WorkingDirectory=%h/.baton-host
207
+ Restart=always
208
+ RestartSec=2
209
+ Environment=HOME=%h
210
+ Environment=PATH=%h/.local/bin:%h/Library/pnpm:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
211
+
212
+ [Install]
213
+ WantedBy=default.target
214
+ `;
215
+ }
216
+
217
+ function getMacPlistPath() {
218
+ return path.join(os.homedir(), "Library", "LaunchAgents", `${SERVICE_LABEL}.plist`);
219
+ }
220
+
221
+ function buildMacPlist() {
222
+ const stdoutPath = path.join(INSTALL_LOG_DIR, "stdout.log");
223
+ const stderrPath = path.join(INSTALL_LOG_DIR, "stderr.log");
224
+ const servicePathEnv = getServicePathEnv();
225
+
226
+ return `<?xml version="1.0" encoding="UTF-8"?>
227
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
228
+ <plist version="1.0">
229
+ <dict>
230
+ <key>Label</key>
231
+ <string>${escapeXml(SERVICE_LABEL)}</string>
232
+ <key>ProgramArguments</key>
233
+ <array>
234
+ <string>${escapeXml(WRAPPER_PATH)}</string>
235
+ </array>
236
+ <key>WorkingDirectory</key>
237
+ <string>${escapeXml(INSTALL_ROOT)}</string>
238
+ <key>RunAtLoad</key>
239
+ <true/>
240
+ <key>KeepAlive</key>
241
+ <true/>
242
+ <key>ProcessType</key>
243
+ <string>Background</string>
244
+ <key>EnvironmentVariables</key>
245
+ <dict>
246
+ <key>HOME</key>
247
+ <string>${escapeXml(os.homedir())}</string>
248
+ <key>PATH</key>
249
+ <string>${escapeXml(servicePathEnv)}</string>
250
+ </dict>
251
+ <key>StandardOutPath</key>
252
+ <string>${escapeXml(stdoutPath)}</string>
253
+ <key>StandardErrorPath</key>
254
+ <string>${escapeXml(stderrPath)}</string>
255
+ </dict>
256
+ </plist>
257
+ `;
258
+ }
259
+
260
+ function runCommand(command, args, options = {}) {
261
+ const result = spawnSync(command, args, {
262
+ encoding: "utf8",
263
+ stdio: ["ignore", "pipe", "pipe"]
264
+ });
265
+
266
+ if (result.error) {
267
+ if (options.allowFailure) {
268
+ return result;
269
+ }
270
+ throw result.error;
271
+ }
272
+
273
+ if (!options.allowFailure && result.status !== 0) {
274
+ const output = (result.stderr || result.stdout || "").trim();
275
+ throw new Error(output || `${command} ${args.join(" ")} 失败,退出码 ${result.status}`);
276
+ }
277
+
278
+ return result;
279
+ }
280
+
281
+ function installLinuxService() {
282
+ const unitPath = getLinuxUnitPath();
283
+ ensureDir(path.dirname(unitPath));
284
+ fs.writeFileSync(unitPath, buildLinuxUnit(), "utf8");
285
+
286
+ runCommand("systemctl", ["--user", "daemon-reload"]);
287
+ runCommand("systemctl", ["--user", "enable", getLinuxServiceName()]);
288
+
289
+ const restartResult = runCommand(
290
+ "systemctl",
291
+ ["--user", "restart", getLinuxServiceName()],
292
+ { allowFailure: true }
293
+ );
294
+
295
+ if (restartResult.status !== 0) {
296
+ runCommand("systemctl", ["--user", "start", getLinuxServiceName()]);
297
+ }
298
+
299
+ return unitPath;
300
+ }
301
+
302
+ function installMacService() {
303
+ const plistPath = getMacPlistPath();
304
+ const launchTarget = `gui/${process.getuid()}`;
305
+ ensureDir(path.dirname(plistPath));
306
+ fs.writeFileSync(plistPath, buildMacPlist(), "utf8");
307
+
308
+ runCommand("launchctl", ["bootout", launchTarget, plistPath], { allowFailure: true });
309
+ runCommand("launchctl", ["bootstrap", launchTarget, plistPath]);
310
+ runCommand("launchctl", ["enable", `${launchTarget}/${SERVICE_LABEL}`], { allowFailure: true });
311
+ runCommand("launchctl", ["kickstart", "-k", `${launchTarget}/${SERVICE_LABEL}`], {
312
+ allowFailure: true
313
+ });
314
+
315
+ return plistPath;
316
+ }
317
+
318
+ function removePathIfExists(targetPath) {
319
+ if (!fs.existsSync(targetPath)) {
320
+ return;
321
+ }
322
+ fs.rmSync(targetPath, { recursive: true, force: true });
323
+ }
324
+
325
+ function restartLinuxService() {
326
+ if (!fs.existsSync(getLinuxUnitPath())) {
327
+ fail("尚未安装 Baton Host systemd 服务,请先执行 npx baton-host@latest service install");
328
+ }
329
+ runCommand("systemctl", ["--user", "restart", getLinuxServiceName()]);
330
+ }
331
+
332
+ function restartMacService() {
333
+ const plistPath = getMacPlistPath();
334
+ if (!fs.existsSync(plistPath)) {
335
+ fail("尚未安装 Baton Host LaunchAgent,请先执行 npx baton-host@latest service install");
336
+ }
337
+ const launchTarget = `gui/${process.getuid()}`;
338
+ runCommand("launchctl", ["bootout", launchTarget, plistPath], { allowFailure: true });
339
+ runCommand("launchctl", ["bootstrap", launchTarget, plistPath]);
340
+ runCommand("launchctl", ["kickstart", "-k", `${launchTarget}/${SERVICE_LABEL}`], {
341
+ allowFailure: true
342
+ });
343
+ }
344
+
345
+ function uninstallLinuxService() {
346
+ runCommand("systemctl", ["--user", "disable", "--now", getLinuxServiceName()], {
347
+ allowFailure: true
348
+ });
349
+ removePathIfExists(getLinuxUnitPath());
350
+ runCommand("systemctl", ["--user", "daemon-reload"], { allowFailure: true });
351
+ }
352
+
353
+ function uninstallMacService() {
354
+ const plistPath = getMacPlistPath();
355
+ const launchTarget = `gui/${process.getuid()}`;
356
+ runCommand("launchctl", ["bootout", launchTarget, plistPath], { allowFailure: true });
357
+ removePathIfExists(plistPath);
358
+ }
359
+
360
+ function cleanupInstallArtifacts() {
361
+ removePathIfExists(path.join(INSTALL_BIN_DIR, "baton-host"));
362
+ removePathIfExists(path.join(INSTALL_BIN_DIR, "cloudflared"));
363
+ removePathIfExists(INSTALL_BIN_DIR);
364
+ removePathIfExists(WRAPPER_PATH);
365
+ removePathIfExists(INSTALL_META_PATH);
366
+ removePathIfExists(INSTALL_LOG_DIR);
367
+
368
+ try {
369
+ const remaining = fs.existsSync(INSTALL_ROOT) ? fs.readdirSync(INSTALL_ROOT) : [];
370
+ if (remaining.length === 0) {
371
+ fs.rmdirSync(INSTALL_ROOT);
372
+ }
373
+ } catch {}
374
+ }
375
+
376
+ function readLinuxStatus() {
377
+ const installed = fs.existsSync(getLinuxUnitPath());
378
+ const enabledResult = installed
379
+ ? runCommand("systemctl", ["--user", "is-enabled", getLinuxServiceName()], { allowFailure: true })
380
+ : { stdout: "", status: 1 };
381
+ const activeResult = installed
382
+ ? runCommand("systemctl", ["--user", "is-active", getLinuxServiceName()], { allowFailure: true })
383
+ : { stdout: "", status: 1 };
384
+
385
+ const enabledState = (enabledResult.stdout || "").trim();
386
+ const activeState = (activeResult.stdout || "").trim();
387
+
388
+ return {
389
+ installed,
390
+ loaded: installed && ["enabled", "enabled-runtime", "static", "indirect"].includes(enabledState),
391
+ running: activeState === "active",
392
+ detail: activeState || enabledState || "not installed",
393
+ serviceFile: getLinuxUnitPath()
394
+ };
395
+ }
396
+
397
+ function readMacStatus() {
398
+ const plistPath = getMacPlistPath();
399
+ const installed = fs.existsSync(plistPath);
400
+ const printResult = installed
401
+ ? runCommand("launchctl", ["print", `gui/${process.getuid()}/${SERVICE_LABEL}`], { allowFailure: true })
402
+ : { stdout: "", stderr: "", status: 1 };
403
+
404
+ const output = `${printResult.stdout || ""}\n${printResult.stderr || ""}`;
405
+ const pidMatch = output.match(/\bpid = (\d+)/);
406
+ const stateMatch = output.match(/\bstate = ([^\n]+)/);
407
+
408
+ return {
409
+ installed,
410
+ loaded: installed && printResult.status === 0,
411
+ running: installed && printResult.status === 0 && !!pidMatch && pidMatch[1] !== "0",
412
+ detail: stateMatch ? stateMatch[1].trim() : (printResult.status === 0 ? "loaded" : "not loaded"),
413
+ serviceFile: plistPath
414
+ };
415
+ }
416
+
417
+ function printServiceStatus() {
418
+ const meta = readInstallMeta();
419
+ const envVars = readEnvFile();
420
+ const platformStatus = process.platform === "linux" ? readLinuxStatus() : readMacStatus();
421
+
422
+ console.log("Baton Host Service Status");
423
+ console.log("");
424
+ console.log(`Installed: ${platformStatus.installed ? "yes" : "no"}`);
425
+ console.log(`Loaded: ${platformStatus.loaded ? "yes" : "no"}`);
426
+ console.log(`Running: ${platformStatus.running ? "yes" : "no"}`);
427
+ console.log(`State: ${platformStatus.detail}`);
428
+ if (meta?.version) {
429
+ console.log(`Version: ${meta.version}`);
430
+ }
431
+ console.log(`Mode: ${envVars.BATON_BRIDGE_MODE || "lan"}`);
432
+ console.log(`Port: ${envVars.PORT || "9966"}`);
433
+ console.log(`Log profile: ${envVars.BRIDGE_LOG_PROFILE || "core"}`);
434
+ console.log(`Binary: ${path.join(INSTALL_BIN_DIR, "baton-host")}`);
435
+ console.log(`Env file: ${ENV_FILE_PATH}`);
436
+ console.log(`Service file: ${platformStatus.serviceFile}`);
437
+ }
438
+
439
+ function ensureSupportedServicePlatform() {
440
+ if (!["linux", "darwin"].includes(process.platform)) {
441
+ fail(`当前平台不支持 service 子命令: ${process.platform}`);
442
+ }
443
+ }
444
+
445
+ function handleServiceInstall() {
446
+ ensureSupportedServicePlatform();
447
+
448
+ const previousVersion = readInstallMeta()?.version || null;
449
+ const { binaryPath, cloudflaredPath, version } = resolveBundledAssets();
450
+
451
+ ensureDir(INSTALL_ROOT);
452
+ ensureDir(INSTALL_BIN_DIR);
453
+ ensureDir(INSTALL_LOG_DIR);
454
+
455
+ copyExecutable(binaryPath, path.join(INSTALL_BIN_DIR, "baton-host"));
456
+ copyExecutable(cloudflaredPath, path.join(INSTALL_BIN_DIR, "cloudflared"));
457
+ ensureDefaultEnvFile();
458
+ writeWrapperScript();
459
+ writeInstallMeta(version);
460
+
461
+ const serviceFile = process.platform === "linux" ? installLinuxService() : installMacService();
462
+ const action = previousVersion && previousVersion !== version
463
+ ? "升级并重启"
464
+ : previousVersion
465
+ ? "覆盖并重启"
466
+ : "安装并启动";
467
+
468
+ console.log(`✅ Baton Host 服务已${action}`);
469
+ console.log(`Version: ${version}`);
470
+ console.log(`Binary: ${path.join(INSTALL_BIN_DIR, "baton-host")}`);
471
+ console.log(`Env file: ${ENV_FILE_PATH}`);
472
+ console.log(`Service file: ${serviceFile}`);
473
+ }
474
+
475
+ function handleServiceRestart() {
476
+ ensureSupportedServicePlatform();
477
+ if (process.platform === "linux") {
478
+ restartLinuxService();
479
+ } else {
480
+ restartMacService();
481
+ }
482
+ console.log("✅ Baton Host 服务已重启");
483
+ }
484
+
485
+ function handleServiceUninstall() {
486
+ ensureSupportedServicePlatform();
487
+ if (process.platform === "linux") {
488
+ uninstallLinuxService();
489
+ } else {
490
+ uninstallMacService();
491
+ }
492
+ cleanupInstallArtifacts();
493
+ console.log("✅ Baton Host 服务已卸载");
494
+ console.log(`保留配置文件: ${ENV_FILE_PATH}`);
495
+ }
496
+
497
+ function printServiceUsage() {
498
+ console.log("Usage:");
499
+ console.log(" npx baton-host@latest service install");
500
+ console.log(" npx baton-host@latest service upgrade");
501
+ console.log(" npx baton-host@latest service restart");
502
+ console.log(" npx baton-host@latest service status");
503
+ console.log(" npx baton-host@latest service uninstall");
504
+ console.log(" npx baton-host@latest service help");
505
+ console.log("");
506
+ console.log("配置文件: ~/.baton-host/.env");
507
+ console.log(" BATON_BRIDGE_MODE=lan|tailscale|cloudflare");
508
+ console.log(" PORT=9966");
509
+ console.log("");
510
+ console.log("说明: install/upgrade 都会覆盖二进制并重启服务");
511
+ }
512
+
513
+ function handleServiceCommand(args) {
514
+ const command = args[0] || "install";
515
+
516
+ if (command === "install" || command === "upgrade") {
517
+ handleServiceInstall();
518
+ return;
519
+ }
520
+
521
+ if (command === "restart") {
522
+ handleServiceRestart();
523
+ return;
524
+ }
525
+
526
+ if (command === "status") {
527
+ printServiceStatus();
528
+ return;
529
+ }
530
+
531
+ if (command === "uninstall") {
532
+ handleServiceUninstall();
533
+ return;
534
+ }
535
+
536
+ if (command === "help" || command === "--help" || command === "-h") {
537
+ printServiceUsage();
538
+ return;
539
+ }
540
+
541
+ printServiceUsage();
542
+ process.exit(1);
543
+ }
544
+
545
+ function spawnHostBinary(args) {
546
+ const { binaryPath, cloudflaredPath } = resolveBundledAssets();
547
+ const child = spawn(binaryPath, args, {
548
+ stdio: "inherit",
549
+ env: {
550
+ ...process.env,
551
+ BATON_CLOUDFLARED_BIN: cloudflaredPath
552
+ }
553
+ });
554
+
555
+ child.on("exit", (code, signal) => {
556
+ if (signal) {
557
+ process.kill(process.pid, signal);
558
+ return;
559
+ }
560
+ process.exit(code ?? 0);
561
+ });
562
+ }
563
+
564
+ function main() {
565
+ const args = process.argv.slice(2);
566
+ if (args[0] === "service") {
567
+ handleServiceCommand(args.slice(1));
568
+ return;
569
+ }
570
+ spawnHostBinary(args);
571
+ }
572
+
573
+ try {
574
+ main();
575
+ } catch (error) {
576
+ fail(error instanceof Error ? error.message : String(error));
577
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "baton-host",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "Baton Bridge Host CLI(二进制分发入口)",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -10,9 +10,9 @@
10
10
  "bin"
11
11
  ],
12
12
  "optionalDependencies": {
13
- "baton-host-darwin-arm64": "0.1.4",
14
- "baton-host-darwin-x64": "0.1.4",
15
- "baton-host-linux-arm64": "0.1.4",
16
- "baton-host-linux-x64": "0.1.4"
13
+ "baton-host-darwin-arm64": "0.1.6",
14
+ "baton-host-darwin-x64": "0.1.6",
15
+ "baton-host-linux-arm64": "0.1.6",
16
+ "baton-host-linux-x64": "0.1.6"
17
17
  }
18
18
  }