foliko 1.1.41 → 1.1.43
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/.claude/settings.local.json +2 -1
- package/cli/src/commands/daemon.js +64 -37
- package/examples/daemon.js +12 -0
- package/package.json +1 -1
|
@@ -210,7 +210,8 @@
|
|
|
210
210
|
"Bash(node -c plugins/qq-plugin.js 2>&1)",
|
|
211
211
|
"Bash(node -c cli/src/commands/daemon.js 2>&1 && node -c cli/src/index.js 2>&1)",
|
|
212
212
|
"Bash(node -c examples/daemon.js 2>&1)",
|
|
213
|
-
"Bash(node -c cli/src/commands/daemon.js 2>&1)"
|
|
213
|
+
"Bash(node -c cli/src/commands/daemon.js 2>&1)",
|
|
214
|
+
"Bash(node -c cli/src/index.js 2>&1)"
|
|
214
215
|
]
|
|
215
216
|
}
|
|
216
217
|
}
|
|
@@ -1,24 +1,36 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Foliko Daemon 命令
|
|
3
|
-
* Usage: foliko start | stop | status
|
|
3
|
+
* Usage: foliko start | stop | status [--path=<dir>]
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
const fs = require('fs');
|
|
7
7
|
const path = require('path');
|
|
8
8
|
const { spawn } = require('child_process');
|
|
9
9
|
|
|
10
|
-
//
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
// Daemon 脚本路径(相对于项目根目录)
|
|
11
|
+
const DAEMON_SCRIPT = path.join(__dirname, '../../../examples/daemon.js');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 获取指定目录的 PID 文件路径
|
|
15
|
+
*/
|
|
16
|
+
function getPidFile(dir) {
|
|
17
|
+
return path.join(dir, '.foliko.pid');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* 获取指定目录的日志文件路径
|
|
22
|
+
*/
|
|
23
|
+
function getLogFile(dir) {
|
|
24
|
+
return path.join(dir, '.foliko.log');
|
|
25
|
+
}
|
|
15
26
|
|
|
16
27
|
/**
|
|
17
28
|
* 获取 PID 文件中的进程 ID
|
|
18
29
|
*/
|
|
19
|
-
function getPid() {
|
|
20
|
-
|
|
21
|
-
|
|
30
|
+
function getPid(dir) {
|
|
31
|
+
const pidFile = getPidFile(dir);
|
|
32
|
+
if (fs.existsSync(pidFile)) {
|
|
33
|
+
return parseInt(fs.readFileSync(pidFile, 'utf8').trim(), 10);
|
|
22
34
|
}
|
|
23
35
|
return null;
|
|
24
36
|
}
|
|
@@ -39,8 +51,10 @@ function isRunning(pid) {
|
|
|
39
51
|
/**
|
|
40
52
|
* 启动守护进程
|
|
41
53
|
*/
|
|
42
|
-
async function startDaemon() {
|
|
43
|
-
const
|
|
54
|
+
async function startDaemon(targetDir) {
|
|
55
|
+
const pidFile = getPidFile(targetDir);
|
|
56
|
+
const logFile = getLogFile(targetDir);
|
|
57
|
+
const existingPid = getPid(targetDir);
|
|
44
58
|
|
|
45
59
|
if (existingPid && isRunning(existingPid)) {
|
|
46
60
|
console.log(`Foliko 已在运行 (PID: ${existingPid})`);
|
|
@@ -48,36 +62,37 @@ async function startDaemon() {
|
|
|
48
62
|
}
|
|
49
63
|
|
|
50
64
|
// 启动子进程
|
|
51
|
-
const child = spawn(process.execPath, [DAEMON_SCRIPT], {
|
|
65
|
+
const child = spawn(process.execPath, [DAEMON_SCRIPT, '--cwd', targetDir], {
|
|
52
66
|
detached: true,
|
|
53
67
|
stdio: 'ignore',
|
|
54
|
-
cwd:
|
|
68
|
+
cwd: targetDir,
|
|
55
69
|
});
|
|
56
70
|
|
|
57
|
-
//
|
|
58
|
-
|
|
59
|
-
fs.writeSync(outFd, `\n=== Foliko started at ${new Date().toISOString()} ===\n`);
|
|
71
|
+
// 写入启动日志
|
|
72
|
+
fs.writeFileSync(logFile, `\n=== Foliko started at ${new Date().toISOString()} ===\n`);
|
|
60
73
|
|
|
61
74
|
// 保存 PID
|
|
62
|
-
fs.writeFileSync(
|
|
75
|
+
fs.writeFileSync(pidFile, child.pid.toString());
|
|
63
76
|
|
|
64
|
-
//
|
|
77
|
+
// 脱离父进程
|
|
65
78
|
child.unref();
|
|
66
79
|
|
|
67
80
|
console.log(`Foliko 已启动 (PID: ${child.pid})`);
|
|
68
|
-
console.log(
|
|
81
|
+
console.log(`工作目录: ${targetDir}`);
|
|
82
|
+
console.log(`日志文件: ${logFile}`);
|
|
69
83
|
}
|
|
70
84
|
|
|
71
85
|
/**
|
|
72
86
|
* 停止守护进程
|
|
73
87
|
*/
|
|
74
|
-
async function stopDaemon() {
|
|
75
|
-
const
|
|
88
|
+
async function stopDaemon(targetDir) {
|
|
89
|
+
const pidFile = getPidFile(targetDir);
|
|
90
|
+
const pid = getPid(targetDir);
|
|
76
91
|
|
|
77
92
|
if (!pid || !isRunning(pid)) {
|
|
78
93
|
console.log('Foliko 未在运行');
|
|
79
|
-
if (fs.existsSync(
|
|
80
|
-
fs.unlinkSync(
|
|
94
|
+
if (fs.existsSync(pidFile)) {
|
|
95
|
+
fs.unlinkSync(pidFile);
|
|
81
96
|
}
|
|
82
97
|
return;
|
|
83
98
|
}
|
|
@@ -88,15 +103,15 @@ async function stopDaemon() {
|
|
|
88
103
|
|
|
89
104
|
// 等待进程结束
|
|
90
105
|
setTimeout(() => {
|
|
91
|
-
if (fs.existsSync(
|
|
92
|
-
fs.unlinkSync(
|
|
106
|
+
if (fs.existsSync(pidFile)) {
|
|
107
|
+
fs.unlinkSync(pidFile);
|
|
93
108
|
}
|
|
94
109
|
console.log('Foliko 已停止');
|
|
95
110
|
}, 2000);
|
|
96
111
|
} catch (err) {
|
|
97
112
|
console.error(`停止失败: ${err.message}`);
|
|
98
|
-
if (fs.existsSync(
|
|
99
|
-
fs.unlinkSync(
|
|
113
|
+
if (fs.existsSync(pidFile)) {
|
|
114
|
+
fs.unlinkSync(pidFile);
|
|
100
115
|
}
|
|
101
116
|
}
|
|
102
117
|
}
|
|
@@ -104,8 +119,8 @@ async function stopDaemon() {
|
|
|
104
119
|
/**
|
|
105
120
|
* 查看状态
|
|
106
121
|
*/
|
|
107
|
-
async function statusDaemon() {
|
|
108
|
-
const pid = getPid();
|
|
122
|
+
async function statusDaemon(targetDir) {
|
|
123
|
+
const pid = getPid(targetDir);
|
|
109
124
|
|
|
110
125
|
if (!pid || !isRunning(pid)) {
|
|
111
126
|
console.log('Foliko 未在运行');
|
|
@@ -113,28 +128,40 @@ async function statusDaemon() {
|
|
|
113
128
|
}
|
|
114
129
|
|
|
115
130
|
console.log(`Foliko 正在运行 (PID: ${pid})`);
|
|
131
|
+
console.log(`工作目录: ${targetDir}`);
|
|
116
132
|
}
|
|
117
133
|
|
|
118
134
|
/**
|
|
119
135
|
* Daemon 命令入口
|
|
120
|
-
* @param {string[]} fullArgs - 完整参数 [command, subCommand]
|
|
121
136
|
*/
|
|
122
|
-
async function daemonCommand(
|
|
123
|
-
const command =
|
|
137
|
+
async function daemonCommand(args) {
|
|
138
|
+
const command = args[0] || 'start';
|
|
139
|
+
|
|
140
|
+
// 解析 --path 参数
|
|
141
|
+
let targetDir = process.cwd();
|
|
142
|
+
for (let i = 1; i < args.length; i++) {
|
|
143
|
+
const arg = args[i];
|
|
144
|
+
if (arg === '--path' && args[i + 1]) {
|
|
145
|
+
targetDir = path.resolve(args[i + 1]);
|
|
146
|
+
i++;
|
|
147
|
+
} else if (arg.startsWith('--path=')) {
|
|
148
|
+
targetDir = path.resolve(arg.split('=')[1]);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
124
151
|
|
|
125
152
|
switch (command) {
|
|
126
153
|
case 'start':
|
|
127
|
-
await startDaemon();
|
|
154
|
+
await startDaemon(targetDir);
|
|
128
155
|
break;
|
|
129
156
|
case 'stop':
|
|
130
|
-
await stopDaemon();
|
|
157
|
+
await stopDaemon(targetDir);
|
|
131
158
|
break;
|
|
132
159
|
case 'status':
|
|
133
|
-
await statusDaemon();
|
|
160
|
+
await statusDaemon(targetDir);
|
|
134
161
|
break;
|
|
135
162
|
default:
|
|
136
|
-
console.log('用法: foliko start | stop | status');
|
|
163
|
+
console.log('用法: foliko start | stop | status [--path=<dir>]');
|
|
137
164
|
}
|
|
138
165
|
}
|
|
139
166
|
|
|
140
|
-
module.exports = { daemonCommand };
|
|
167
|
+
module.exports = { daemonCommand };
|
package/examples/daemon.js
CHANGED
|
@@ -4,6 +4,18 @@
|
|
|
4
4
|
* 持续运行,不退出
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
// 解析命令行参数 --cwd <path>
|
|
8
|
+
const cwdArg = process.argv.find((arg) => arg === '--cwd');
|
|
9
|
+
const daemonCwd = cwdArg ? process.argv[process.argv.indexOf(cwdArg) + 1] : process.cwd();
|
|
10
|
+
|
|
11
|
+
// 切换到工作目录
|
|
12
|
+
if (daemonCwd !== process.cwd()) {
|
|
13
|
+
process.chdir(daemonCwd);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// 加载环境变量
|
|
17
|
+
require('dotenv').config({ path: path.join(process.cwd(), '.env') });
|
|
18
|
+
|
|
7
19
|
const { Framework } = require('../src');
|
|
8
20
|
const fs = require('fs');
|
|
9
21
|
const path = require('path');
|