openilink-app-runner 0.2.0 → 0.3.0

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.
@@ -1,2 +1,2 @@
1
- export declare function install(configPath: string): void;
1
+ export declare function install(configPath?: string): void;
2
2
  export declare function uninstall(): void;
@@ -39,20 +39,17 @@ const fs = __importStar(require("fs"));
39
39
  const os = __importStar(require("os"));
40
40
  const path = __importStar(require("path"));
41
41
  const child_process_1 = require("child_process");
42
+ const config_1 = require("./config");
42
43
  const SERVICE_NAME = "openilink-app-runner";
43
44
  function getBinPath() {
44
45
  try {
45
46
  return (0, child_process_1.execSync)("which openilink-app-runner", { encoding: "utf-8" }).trim();
46
47
  }
47
48
  catch {
48
- // Fallback: resolve from node_modules
49
49
  return path.resolve(__dirname, "../bin/runner.js");
50
50
  }
51
51
  }
52
- function getNodePath() {
53
- return process.execPath;
54
- }
55
- // ========== Linux (systemd) ==========
52
+ // ========== Linux (systemd --user) ==========
56
53
  function systemdUnit(configPath) {
57
54
  const absConfig = path.resolve(configPath);
58
55
  const binPath = getBinPath();
@@ -70,37 +67,43 @@ RestartSec=5
70
67
  Environment=NODE_ENV=production
71
68
 
72
69
  [Install]
73
- WantedBy=multi-user.target
70
+ WantedBy=default.target
74
71
  `;
75
72
  }
76
73
  function installSystemd(configPath) {
77
- const unitPath = `/etc/systemd/system/${SERVICE_NAME}.service`;
78
- const unit = systemdUnit(configPath);
79
- fs.writeFileSync(unitPath, unit);
80
- (0, child_process_1.execSync)("systemctl daemon-reload");
81
- (0, child_process_1.execSync)(`systemctl enable ${SERVICE_NAME}`);
82
- (0, child_process_1.execSync)(`systemctl start ${SERVICE_NAME}`);
83
- console.log(`✓ 已安装 systemd 服务`);
74
+ const userDir = path.join(os.homedir(), ".config/systemd/user");
75
+ fs.mkdirSync(userDir, { recursive: true });
76
+ const unitPath = path.join(userDir, `${SERVICE_NAME}.service`);
77
+ fs.writeFileSync(unitPath, systemdUnit(configPath));
78
+ (0, child_process_1.execSync)(`systemctl --user daemon-reload`);
79
+ (0, child_process_1.execSync)(`systemctl --user enable ${SERVICE_NAME}`);
80
+ (0, child_process_1.execSync)(`systemctl --user start ${SERVICE_NAME}`);
81
+ // Enable lingering so user services run without login
82
+ try {
83
+ (0, child_process_1.execSync)(`loginctl enable-linger ${os.userInfo().username}`, { stdio: "ignore" });
84
+ }
85
+ catch { }
86
+ console.log(`✓ 已安装 systemd 用户服务(无需 sudo)`);
84
87
  console.log(` 服务文件: ${unitPath}`);
85
88
  console.log(` 配置文件: ${path.resolve(configPath)}`);
86
- console.log(` 查看状态: systemctl status ${SERVICE_NAME}`);
87
- console.log(` 查看日志: journalctl -u ${SERVICE_NAME} -f`);
89
+ console.log(` 查看状态: systemctl --user status ${SERVICE_NAME}`);
90
+ console.log(` 查看日志: journalctl --user -u ${SERVICE_NAME} -f`);
88
91
  }
89
92
  function uninstallSystemd() {
90
93
  try {
91
- (0, child_process_1.execSync)(`systemctl stop ${SERVICE_NAME}`, { stdio: "ignore" });
94
+ (0, child_process_1.execSync)(`systemctl --user stop ${SERVICE_NAME}`, { stdio: "ignore" });
92
95
  }
93
96
  catch { }
94
97
  try {
95
- (0, child_process_1.execSync)(`systemctl disable ${SERVICE_NAME}`, { stdio: "ignore" });
98
+ (0, child_process_1.execSync)(`systemctl --user disable ${SERVICE_NAME}`, { stdio: "ignore" });
96
99
  }
97
100
  catch { }
98
- const unitPath = `/etc/systemd/system/${SERVICE_NAME}.service`;
101
+ const unitPath = path.join(os.homedir(), `.config/systemd/user/${SERVICE_NAME}.service`);
99
102
  if (fs.existsSync(unitPath)) {
100
103
  fs.unlinkSync(unitPath);
101
- (0, child_process_1.execSync)("systemctl daemon-reload");
104
+ (0, child_process_1.execSync)(`systemctl --user daemon-reload`);
102
105
  }
103
- console.log(`✓ 已卸载 systemd 服务`);
106
+ console.log(`✓ 已卸载 systemd 用户服务`);
104
107
  }
105
108
  // ========== macOS (launchd) ==========
106
109
  function launchdPlist(configPath) {
@@ -133,47 +136,46 @@ function launchdPlist(configPath) {
133
136
  `;
134
137
  }
135
138
  function installLaunchd(configPath) {
136
- const plistPath = path.join(os.homedir(), `Library/LaunchAgents/com.openilink.app-runner.plist`);
137
- const plist = launchdPlist(configPath);
139
+ const plistPath = path.join(os.homedir(), "Library/LaunchAgents/com.openilink.app-runner.plist");
138
140
  fs.mkdirSync(path.dirname(plistPath), { recursive: true });
139
- fs.writeFileSync(plistPath, plist);
141
+ fs.writeFileSync(plistPath, launchdPlist(configPath));
140
142
  try {
141
143
  (0, child_process_1.execSync)(`launchctl unload ${plistPath}`, { stdio: "ignore" });
142
144
  }
143
145
  catch { }
144
146
  (0, child_process_1.execSync)(`launchctl load ${plistPath}`);
145
- console.log(`✓ 已安装 launchd 服务`);
147
+ console.log(`✓ 已安装 launchd 服务(无需 sudo)`);
146
148
  console.log(` 配置文件: ${plistPath}`);
147
149
  console.log(` 日志: ~/Library/Logs/openilink-app-runner.log`);
148
150
  }
149
151
  function uninstallLaunchd() {
150
- const plistPath = path.join(os.homedir(), `Library/LaunchAgents/com.openilink.app-runner.plist`);
152
+ const plistPath = path.join(os.homedir(), "Library/LaunchAgents/com.openilink.app-runner.plist");
151
153
  try {
152
154
  (0, child_process_1.execSync)(`launchctl unload ${plistPath}`, { stdio: "ignore" });
153
155
  }
154
156
  catch { }
155
- if (fs.existsSync(plistPath)) {
157
+ if (fs.existsSync(plistPath))
156
158
  fs.unlinkSync(plistPath);
157
- }
158
159
  console.log(`✓ 已卸载 launchd 服务`);
159
160
  }
160
161
  // ========== Public API ==========
161
162
  function install(configPath) {
162
- const absConfig = path.resolve(configPath);
163
+ const resolved = configPath || (0, config_1.getConfigPath)();
164
+ const absConfig = path.resolve(resolved);
163
165
  if (!fs.existsSync(absConfig)) {
164
166
  console.error(`配置文件不存在: ${absConfig}`);
165
167
  console.error(`请先运行: openilink-app-runner init --hub-url <url> --token <token>`);
166
168
  process.exit(1);
167
169
  }
168
170
  if (os.platform() === "darwin") {
169
- installLaunchd(configPath);
171
+ installLaunchd(absConfig);
170
172
  }
171
173
  else if (os.platform() === "linux") {
172
- installSystemd(configPath);
174
+ installSystemd(absConfig);
173
175
  }
174
176
  else {
175
177
  console.error(`不支持的平台: ${os.platform()}`);
176
- console.error(`请手动运行: openilink-app-runner start --config ${absConfig}`);
178
+ console.error(`请手动运行: openilink-app-runner start`);
177
179
  process.exit(1);
178
180
  }
179
181
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openilink-app-runner",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Run local commands as OpeniLink Hub App tools — bridge CLI to WeChat",
5
5
  "bin": {
6
6
  "openilink-app-runner": "dist/bin/runner.js"