fdb2 1.0.10 → 1.0.12
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/bin/fdb2.js +122 -23
- package/dist/public/explorer.css +185 -103
- package/dist/public/explorer.js +855 -896
- package/dist/public/index.css +30 -2
- package/dist/public/index.js +61 -16
- package/dist/public/vue.js +18 -25
- package/package.json +20 -20
- package/src/components/dataGrid/index.vue +62 -4
- package/src/platform/database/components/database-detail.vue +31 -6
- package/src/platform/database/components/table-data-grid.vue +273 -0
- package/src/platform/database/components/table-detail.vue +64 -267
- package/server.pid +0 -1
package/bin/fdb2.js
CHANGED
|
@@ -4,10 +4,43 @@ const { exec, spawn, execSync, spawnSync } = require('child_process');
|
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const fs = require('fs');
|
|
6
6
|
const net = require('net');
|
|
7
|
+
const os = require('os');
|
|
7
8
|
|
|
8
9
|
// 项目根目录
|
|
9
10
|
const projectRoot = path.resolve(__dirname, '..');
|
|
10
11
|
|
|
12
|
+
// 获取 PID 文件路径
|
|
13
|
+
function getPidFilePath() {
|
|
14
|
+
const dataDir = process.env.DB_TOOL_DATA_DIR || path.join(os.homedir(), '.fdb2');
|
|
15
|
+
if (!fs.existsSync(dataDir)) {
|
|
16
|
+
fs.mkdirSync(dataDir, { recursive: true });
|
|
17
|
+
}
|
|
18
|
+
return path.join(dataDir, 'fdb2.server.pid');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// 读取 PID
|
|
22
|
+
function readPid() {
|
|
23
|
+
const pidFilePath = getPidFilePath();
|
|
24
|
+
if (fs.existsSync(pidFilePath)) {
|
|
25
|
+
return parseInt(fs.readFileSync(pidFilePath, 'utf8'));
|
|
26
|
+
}
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// 写入 PID
|
|
31
|
+
function writePid(pid) {
|
|
32
|
+
const pidFilePath = getPidFilePath();
|
|
33
|
+
fs.writeFileSync(pidFilePath, pid.toString());
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// 删除 PID
|
|
37
|
+
function deletePid() {
|
|
38
|
+
const pidFilePath = getPidFilePath();
|
|
39
|
+
if (fs.existsSync(pidFilePath)) {
|
|
40
|
+
fs.unlinkSync(pidFilePath);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
11
44
|
// 解析命令行参数
|
|
12
45
|
const args = process.argv.slice(2);
|
|
13
46
|
const command = args[0] || 'help';
|
|
@@ -74,17 +107,16 @@ async function startProject() {
|
|
|
74
107
|
console.log('Starting FDB2 project...');
|
|
75
108
|
|
|
76
109
|
// 检查 PID 文件是否存在,如果存在则说明服务器已经在运行
|
|
77
|
-
const
|
|
78
|
-
if (
|
|
110
|
+
const pid = readPid();
|
|
111
|
+
if (pid) {
|
|
79
112
|
try {
|
|
80
|
-
const pid = parseInt(fs.readFileSync(pidFilePath, 'utf8'));
|
|
81
113
|
process.kill(pid, 0);
|
|
82
114
|
console.log('Server is already running with PID:', pid);
|
|
83
115
|
return;
|
|
84
116
|
} catch (error) {
|
|
85
117
|
if (error.code === 'ESRCH') {
|
|
86
118
|
console.log('Cleaning up stale PID file...');
|
|
87
|
-
|
|
119
|
+
deletePid();
|
|
88
120
|
}
|
|
89
121
|
}
|
|
90
122
|
}
|
|
@@ -120,24 +152,40 @@ async function startProject() {
|
|
|
120
152
|
// 日志文件路径
|
|
121
153
|
const logFilePath = path.join(projectRoot, 'server.log');
|
|
122
154
|
|
|
123
|
-
//
|
|
124
|
-
|
|
125
|
-
|
|
155
|
+
// 安全地创建日志文件写入流,忽略错误
|
|
156
|
+
function createLogFileStream(logFilePath) {
|
|
157
|
+
try {
|
|
158
|
+
const fd = fs.openSync(logFilePath, 'a');
|
|
159
|
+
console.log(`Log file created: ${logFilePath}`);
|
|
160
|
+
return fd;
|
|
161
|
+
} catch (error) {
|
|
162
|
+
console.warn(`Failed to create log file ${logFilePath}: ${error.message}`);
|
|
163
|
+
console.warn('Logs will only be written to console.');
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// 创建日志文件流
|
|
169
|
+
const logFileFd = createLogFileStream(logFilePath);
|
|
126
170
|
|
|
127
171
|
// 使用 node 命令启动服务器(异步,后台运行)
|
|
128
172
|
const child = spawn(cmd, args, {
|
|
129
173
|
cwd: projectRoot,
|
|
130
174
|
detached: true,
|
|
131
|
-
stdio: ['ignore',
|
|
175
|
+
stdio: ['ignore', logFileFd || 'inherit', logFileFd || 'inherit']
|
|
132
176
|
});
|
|
133
177
|
|
|
134
178
|
// 解除父子进程关联,让子进程在后台独立运行
|
|
135
179
|
child.unref();
|
|
136
180
|
|
|
137
181
|
// 保存 PID 到文件
|
|
138
|
-
|
|
182
|
+
writePid(child.pid);
|
|
139
183
|
|
|
140
|
-
|
|
184
|
+
if (logFileFd) {
|
|
185
|
+
console.log('Logs are written to:', logFilePath);
|
|
186
|
+
} else {
|
|
187
|
+
console.log('Logs are written to console only');
|
|
188
|
+
}
|
|
141
189
|
console.log('Server started successfully with PID:', child.pid);
|
|
142
190
|
console.log('Server is running in the background');
|
|
143
191
|
console.log(`Server is running at http://localhost:${port}`);
|
|
@@ -147,32 +195,84 @@ async function startProject() {
|
|
|
147
195
|
function stopProject() {
|
|
148
196
|
console.log('Stopping FDB2 project...');
|
|
149
197
|
|
|
150
|
-
// 读取 PID
|
|
151
|
-
const
|
|
198
|
+
// 读取 PID
|
|
199
|
+
const pid = readPid();
|
|
152
200
|
|
|
153
|
-
if (!
|
|
201
|
+
if (!pid) {
|
|
154
202
|
console.log('No server process found (PID file not exists)');
|
|
155
203
|
return;
|
|
156
204
|
}
|
|
157
205
|
|
|
158
206
|
try {
|
|
159
|
-
// 读取 PID
|
|
160
|
-
const pid = parseInt(fs.readFileSync(pidFilePath, 'utf8'));
|
|
161
207
|
console.log(`Stopping server process with PID: ${pid}`);
|
|
162
208
|
|
|
163
|
-
// 发送终止信号
|
|
164
|
-
|
|
209
|
+
// 发送终止信号 - 尝试不同的信号
|
|
210
|
+
try {
|
|
211
|
+
// 首先尝试 SIGTERM (15) - 正常终止
|
|
212
|
+
process.kill(pid, 'SIGTERM');
|
|
213
|
+
console.log('SIGTERM signal sent');
|
|
214
|
+
|
|
215
|
+
// 等待一段时间(2秒)
|
|
216
|
+
const startTime = Date.now();
|
|
217
|
+
const maxWaitTime = 2000; // 2秒
|
|
218
|
+
let processExists = true;
|
|
219
|
+
|
|
220
|
+
while (Date.now() - startTime < maxWaitTime) {
|
|
221
|
+
try {
|
|
222
|
+
// 检查进程是否还存在
|
|
223
|
+
process.kill(pid, 0);
|
|
224
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 100); // 等待100ms
|
|
225
|
+
} catch (err) {
|
|
226
|
+
if (err.code === 'ESRCH') {
|
|
227
|
+
processExists = false;
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// 如果进程仍然存在,尝试 SIGKILL (9) - 强制终止
|
|
234
|
+
if (processExists) {
|
|
235
|
+
console.log('Process still exists, sending SIGKILL...');
|
|
236
|
+
try {
|
|
237
|
+
process.kill(pid, 'SIGKILL');
|
|
238
|
+
console.log('SIGKILL signal sent');
|
|
239
|
+
|
|
240
|
+
// 再等待500ms
|
|
241
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 500);
|
|
242
|
+
} catch (killErr) {
|
|
243
|
+
// SIGKILL 失败可能表示我们没有权限
|
|
244
|
+
if (killErr.code === 'EPERM') {
|
|
245
|
+
console.error('Insufficient permissions to kill process');
|
|
246
|
+
console.error('Try running with sudo or manually kill the process:');
|
|
247
|
+
console.error(` sudo kill -9 ${pid}`);
|
|
248
|
+
}
|
|
249
|
+
throw killErr;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
} catch (killError) {
|
|
253
|
+
// 如果 kill 操作失败,检查错误类型
|
|
254
|
+
if (killError.code === 'EPERM') {
|
|
255
|
+
// 权限不足
|
|
256
|
+
console.error('Insufficient permissions to kill process');
|
|
257
|
+
console.error('Try running with sudo or manually kill the process:');
|
|
258
|
+
console.error(` sudo kill -9 ${pid}`);
|
|
259
|
+
throw killError;
|
|
260
|
+
} else if (killError.code === 'ESRCH') {
|
|
261
|
+
// 进程不存在
|
|
262
|
+
console.log('Process not found');
|
|
263
|
+
} else {
|
|
264
|
+
throw killError;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
165
267
|
|
|
166
268
|
// 删除 PID 文件
|
|
167
|
-
|
|
269
|
+
deletePid();
|
|
168
270
|
console.log('Server stopped successfully');
|
|
169
271
|
} catch (error) {
|
|
170
272
|
// 如果进程不存在(ESRCH 错误),也删除 PID 文件
|
|
171
273
|
if (error.code === 'ESRCH') {
|
|
172
274
|
console.log('Server process not found, cleaning up PID file');
|
|
173
|
-
|
|
174
|
-
fs.unlinkSync(pidFilePath);
|
|
175
|
-
}
|
|
275
|
+
deletePid();
|
|
176
276
|
} else {
|
|
177
277
|
console.error('Failed to stop server:', error.message);
|
|
178
278
|
}
|
|
@@ -196,8 +296,7 @@ function restartProject() {
|
|
|
196
296
|
console.log('Waiting for server process to stop...');
|
|
197
297
|
for (let i = 0; i < 10; i++) {
|
|
198
298
|
// 检查 PID 文件是否存在
|
|
199
|
-
|
|
200
|
-
if (!fs.existsSync(pidFilePath)) {
|
|
299
|
+
if (!readPid()) {
|
|
201
300
|
break;
|
|
202
301
|
}
|
|
203
302
|
// 等待 100 毫秒
|