xray-manager 1.0.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.
- package/LICENSE +21 -0
- package/README.md +798 -0
- package/dist/cli.d.ts +11 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +113 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/config.d.ts +49 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +295 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/interactive.d.ts +83 -0
- package/dist/commands/interactive.d.ts.map +1 -0
- package/dist/commands/interactive.js +362 -0
- package/dist/commands/interactive.js.map +1 -0
- package/dist/commands/logs.d.ts +43 -0
- package/dist/commands/logs.d.ts.map +1 -0
- package/dist/commands/logs.js +257 -0
- package/dist/commands/logs.js.map +1 -0
- package/dist/commands/service.d.ts +43 -0
- package/dist/commands/service.d.ts.map +1 -0
- package/dist/commands/service.js +177 -0
- package/dist/commands/service.js.map +1 -0
- package/dist/commands/user.d.ts +43 -0
- package/dist/commands/user.d.ts.map +1 -0
- package/dist/commands/user.js +212 -0
- package/dist/commands/user.js.map +1 -0
- package/dist/constants/exit-codes.d.ts +49 -0
- package/dist/constants/exit-codes.d.ts.map +1 -0
- package/dist/constants/exit-codes.js +100 -0
- package/dist/constants/exit-codes.js.map +1 -0
- package/dist/constants/paths.d.ts +57 -0
- package/dist/constants/paths.d.ts.map +1 -0
- package/dist/constants/paths.js +72 -0
- package/dist/constants/paths.js.map +1 -0
- package/dist/constants/timeouts.d.ts +84 -0
- package/dist/constants/timeouts.d.ts.map +1 -0
- package/dist/constants/timeouts.js +111 -0
- package/dist/constants/timeouts.js.map +1 -0
- package/dist/services/config-manager.d.ts +66 -0
- package/dist/services/config-manager.d.ts.map +1 -0
- package/dist/services/config-manager.js +206 -0
- package/dist/services/config-manager.js.map +1 -0
- package/dist/services/log-manager.d.ts +113 -0
- package/dist/services/log-manager.d.ts.map +1 -0
- package/dist/services/log-manager.js +288 -0
- package/dist/services/log-manager.js.map +1 -0
- package/dist/services/systemd-manager.d.ts +197 -0
- package/dist/services/systemd-manager.d.ts.map +1 -0
- package/dist/services/systemd-manager.js +458 -0
- package/dist/services/systemd-manager.js.map +1 -0
- package/dist/services/user-manager.d.ts +63 -0
- package/dist/services/user-manager.d.ts.map +1 -0
- package/dist/services/user-manager.js +219 -0
- package/dist/services/user-manager.js.map +1 -0
- package/dist/types/config.d.ts +256 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +7 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/service.d.ts +96 -0
- package/dist/types/service.d.ts.map +1 -0
- package/dist/types/service.js +7 -0
- package/dist/types/service.js.map +1 -0
- package/dist/types/user.d.ts +114 -0
- package/dist/types/user.d.ts.map +1 -0
- package/dist/types/user.js +7 -0
- package/dist/types/user.js.map +1 -0
- package/dist/utils/clipboard.d.ts +21 -0
- package/dist/utils/clipboard.d.ts.map +1 -0
- package/dist/utils/clipboard.js +45 -0
- package/dist/utils/clipboard.js.map +1 -0
- package/dist/utils/format.d.ts +93 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/dist/utils/format.js +242 -0
- package/dist/utils/format.js.map +1 -0
- package/dist/utils/logger.d.ts +113 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +260 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/preflight.d.ts +57 -0
- package/dist/utils/preflight.d.ts.map +1 -0
- package/dist/utils/preflight.js +215 -0
- package/dist/utils/preflight.js.map +1 -0
- package/dist/utils/validator.d.ts +102 -0
- package/dist/utils/validator.d.ts.map +1 -0
- package/dist/utils/validator.js +238 -0
- package/dist/utils/validator.js.map +1 -0
- package/dist/utils/which.d.ts +13 -0
- package/dist/utils/which.d.ts.map +1 -0
- package/dist/utils/which.js +28 -0
- package/dist/utils/which.js.map +1 -0
- package/package.json +69 -0
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Interactive Menu Implementation
|
|
4
|
+
*
|
|
5
|
+
* Provides the main interactive menu system for the CLI tool
|
|
6
|
+
*
|
|
7
|
+
* @module commands/interactive
|
|
8
|
+
*/
|
|
9
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
10
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
11
|
+
};
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.MenuStack = void 0;
|
|
14
|
+
exports.getMenuContext = getMenuContext;
|
|
15
|
+
exports.formatMenuHeader = formatMenuHeader;
|
|
16
|
+
exports.getMainMenuOptions = getMainMenuOptions;
|
|
17
|
+
exports.getMenuDepth = getMenuDepth;
|
|
18
|
+
exports.formatMenuOption = formatMenuOption;
|
|
19
|
+
exports.showMenu = showMenu;
|
|
20
|
+
exports.handleMenuSelection = handleMenuSelection;
|
|
21
|
+
exports.handleSigInt = handleSigInt;
|
|
22
|
+
exports.startInteractiveMenu = startInteractiveMenu;
|
|
23
|
+
const prompts_1 = require("@inquirer/prompts");
|
|
24
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
25
|
+
const logger_1 = __importDefault(require("../utils/logger"));
|
|
26
|
+
const exit_codes_1 = require("../constants/exit-codes");
|
|
27
|
+
const systemd_manager_1 = require("../services/systemd-manager");
|
|
28
|
+
const user_manager_1 = require("../services/user-manager");
|
|
29
|
+
const service_1 = require("./service");
|
|
30
|
+
const user_1 = require("./user");
|
|
31
|
+
/**
|
|
32
|
+
* Menu stack for navigation
|
|
33
|
+
*/
|
|
34
|
+
class MenuStack {
|
|
35
|
+
constructor() {
|
|
36
|
+
this.stack = [];
|
|
37
|
+
}
|
|
38
|
+
push(menu) {
|
|
39
|
+
this.stack.push(menu);
|
|
40
|
+
}
|
|
41
|
+
pop() {
|
|
42
|
+
if (this.stack.length === 0) {
|
|
43
|
+
throw new Error('Cannot pop from empty menu stack');
|
|
44
|
+
}
|
|
45
|
+
return this.stack.pop();
|
|
46
|
+
}
|
|
47
|
+
current() {
|
|
48
|
+
return this.stack[this.stack.length - 1];
|
|
49
|
+
}
|
|
50
|
+
depth() {
|
|
51
|
+
return this.stack.length;
|
|
52
|
+
}
|
|
53
|
+
canGoBack() {
|
|
54
|
+
return this.stack.length > 0;
|
|
55
|
+
}
|
|
56
|
+
clear() {
|
|
57
|
+
this.stack = [];
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
exports.MenuStack = MenuStack;
|
|
61
|
+
// Global menu stack instance
|
|
62
|
+
const menuStack = new MenuStack();
|
|
63
|
+
/**
|
|
64
|
+
* Get menu context (service status, user count)
|
|
65
|
+
*/
|
|
66
|
+
async function getMenuContext(options = {}) {
|
|
67
|
+
const serviceName = options.serviceName || 'xray';
|
|
68
|
+
try {
|
|
69
|
+
const systemdManager = new systemd_manager_1.SystemdManager(serviceName);
|
|
70
|
+
const userManager = new user_manager_1.UserManager(options.configPath, serviceName);
|
|
71
|
+
const [status, users] = await Promise.all([
|
|
72
|
+
systemdManager.getStatus(),
|
|
73
|
+
userManager.listUsers(),
|
|
74
|
+
]);
|
|
75
|
+
return {
|
|
76
|
+
serviceStatus: status.healthy ? 'active' : status.active ? status.subState : 'inactive',
|
|
77
|
+
userCount: users.length,
|
|
78
|
+
lastUpdated: new Date(),
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
// If service status fails, return unknown
|
|
83
|
+
return {
|
|
84
|
+
serviceStatus: 'unknown',
|
|
85
|
+
userCount: 0,
|
|
86
|
+
lastUpdated: new Date(),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Format menu header with context
|
|
92
|
+
*/
|
|
93
|
+
function formatMenuHeader(context) {
|
|
94
|
+
const status = context.serviceStatus || 'unknown';
|
|
95
|
+
const userCount = context.userCount || 0;
|
|
96
|
+
const statusColor = status === 'active' ? chalk_1.default.green : status === 'inactive' ? chalk_1.default.red : chalk_1.default.yellow;
|
|
97
|
+
return `${chalk_1.default.gray('服务状态:')} ${statusColor(status)} ${chalk_1.default.gray('用户数:')} ${chalk_1.default.cyan(String(userCount))}`;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Get main menu options
|
|
101
|
+
*/
|
|
102
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
103
|
+
function getMainMenuOptions() {
|
|
104
|
+
return [
|
|
105
|
+
{
|
|
106
|
+
name: chalk_1.default.cyan('📊 查看服务状态'),
|
|
107
|
+
value: 'service-status',
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
name: chalk_1.default.green('🚀 启动服务'),
|
|
111
|
+
value: 'service-start',
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
name: chalk_1.default.red('🛑 停止服务'),
|
|
115
|
+
value: 'service-stop',
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
name: chalk_1.default.yellow('🔄 重启服务'),
|
|
119
|
+
value: 'service-restart',
|
|
120
|
+
},
|
|
121
|
+
{ type: 'separator' },
|
|
122
|
+
{
|
|
123
|
+
name: chalk_1.default.blue('👥 用户管理'),
|
|
124
|
+
value: 'user',
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
name: chalk_1.default.magenta('⚙️ 配置管理'),
|
|
128
|
+
value: 'config',
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
name: chalk_1.default.gray('📝 查看日志'),
|
|
132
|
+
value: 'logs',
|
|
133
|
+
},
|
|
134
|
+
{ type: 'separator' },
|
|
135
|
+
{
|
|
136
|
+
name: chalk_1.default.red('❌ 退出'),
|
|
137
|
+
value: 'exit',
|
|
138
|
+
},
|
|
139
|
+
];
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Get menu depth (for Constitution compliance - max 3 levels)
|
|
143
|
+
*/
|
|
144
|
+
function getMenuDepth() {
|
|
145
|
+
// Main menu (1) -> Submenu (2) -> Action (3)
|
|
146
|
+
return 3;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Format a menu option
|
|
150
|
+
*/
|
|
151
|
+
function formatMenuOption(name, value) {
|
|
152
|
+
// Add icon based on value type
|
|
153
|
+
let icon = '•';
|
|
154
|
+
if (value.includes('service'))
|
|
155
|
+
icon = '⚙️';
|
|
156
|
+
else if (value.includes('user'))
|
|
157
|
+
icon = '👤';
|
|
158
|
+
else if (value.includes('config'))
|
|
159
|
+
icon = '🔧';
|
|
160
|
+
else if (value.includes('log'))
|
|
161
|
+
icon = '📄';
|
|
162
|
+
return {
|
|
163
|
+
name: `${icon} ${name}`,
|
|
164
|
+
value,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Show a menu and get user selection
|
|
169
|
+
*/
|
|
170
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
171
|
+
async function showMenu(options, message = '请选择操作:') {
|
|
172
|
+
const answer = await (0, prompts_1.select)({
|
|
173
|
+
message,
|
|
174
|
+
choices: options,
|
|
175
|
+
});
|
|
176
|
+
return answer;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Handle menu selection
|
|
180
|
+
*/
|
|
181
|
+
async function handleMenuSelection(selection, options) {
|
|
182
|
+
switch (selection) {
|
|
183
|
+
case 'exit':
|
|
184
|
+
return true; // Signal to exit
|
|
185
|
+
case 'service-status':
|
|
186
|
+
logger_1.default.newline();
|
|
187
|
+
await (0, service_1.displayServiceStatus)(options);
|
|
188
|
+
await promptContinue();
|
|
189
|
+
return false;
|
|
190
|
+
case 'service-start':
|
|
191
|
+
logger_1.default.newline();
|
|
192
|
+
await (0, service_1.startService)(options);
|
|
193
|
+
await promptContinue();
|
|
194
|
+
return false;
|
|
195
|
+
case 'service-stop':
|
|
196
|
+
logger_1.default.newline();
|
|
197
|
+
const confirmStop = await (0, prompts_1.confirm)({
|
|
198
|
+
message: chalk_1.default.yellow('⚠️ 确定要停止服务吗?这将中断所有连接。'),
|
|
199
|
+
default: false,
|
|
200
|
+
});
|
|
201
|
+
if (confirmStop) {
|
|
202
|
+
await (0, service_1.stopService)(options);
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
logger_1.default.info('已取消停止操作');
|
|
206
|
+
}
|
|
207
|
+
await promptContinue();
|
|
208
|
+
return false;
|
|
209
|
+
case 'service-restart':
|
|
210
|
+
logger_1.default.newline();
|
|
211
|
+
const confirmRestart = await (0, prompts_1.confirm)({
|
|
212
|
+
message: chalk_1.default.yellow('⚠️ 确定要重启服务吗?'),
|
|
213
|
+
default: true,
|
|
214
|
+
});
|
|
215
|
+
if (confirmRestart) {
|
|
216
|
+
await (0, service_1.restartService)(options);
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
logger_1.default.info('已取消重启操作');
|
|
220
|
+
}
|
|
221
|
+
await promptContinue();
|
|
222
|
+
return false;
|
|
223
|
+
case 'user':
|
|
224
|
+
// Show user management submenu
|
|
225
|
+
return await handleUserManagementMenu(options);
|
|
226
|
+
case 'config':
|
|
227
|
+
logger_1.default.info('配置管理功能即将推出...');
|
|
228
|
+
await promptContinue();
|
|
229
|
+
return false;
|
|
230
|
+
case 'logs':
|
|
231
|
+
logger_1.default.info('日志查看功能即将推出...');
|
|
232
|
+
await promptContinue();
|
|
233
|
+
return false;
|
|
234
|
+
default:
|
|
235
|
+
logger_1.default.warn(`未知选项: ${selection}`);
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Handle user management submenu
|
|
241
|
+
*/
|
|
242
|
+
async function handleUserManagementMenu(options) {
|
|
243
|
+
while (true) {
|
|
244
|
+
logger_1.default.newline();
|
|
245
|
+
logger_1.default.separator();
|
|
246
|
+
console.log(chalk_1.default.bold.cyan('👥 用户管理'));
|
|
247
|
+
logger_1.default.separator();
|
|
248
|
+
logger_1.default.newline();
|
|
249
|
+
const userMenuOptions = [
|
|
250
|
+
{ name: chalk_1.default.cyan('📋 查看用户列表'), value: 'user-list' },
|
|
251
|
+
{ name: chalk_1.default.green('➕ 添加用户'), value: 'user-add' },
|
|
252
|
+
{ name: chalk_1.default.red('➖ 删除用户'), value: 'user-delete' },
|
|
253
|
+
{ name: chalk_1.default.blue('📤 显示分享链接'), value: 'user-share' },
|
|
254
|
+
{ type: 'separator' },
|
|
255
|
+
{ name: chalk_1.default.gray('⬅️ 返回主菜单'), value: 'back' },
|
|
256
|
+
];
|
|
257
|
+
const selection = await showMenu(userMenuOptions, chalk_1.default.bold('请选择操作:'));
|
|
258
|
+
switch (selection) {
|
|
259
|
+
case 'back':
|
|
260
|
+
return false; // Return to main menu
|
|
261
|
+
case 'user-list':
|
|
262
|
+
logger_1.default.newline();
|
|
263
|
+
await (0, user_1.listUsers)(options);
|
|
264
|
+
await promptContinue();
|
|
265
|
+
break;
|
|
266
|
+
case 'user-add':
|
|
267
|
+
logger_1.default.newline();
|
|
268
|
+
await (0, user_1.addUser)(options);
|
|
269
|
+
await promptContinue();
|
|
270
|
+
break;
|
|
271
|
+
case 'user-delete':
|
|
272
|
+
logger_1.default.newline();
|
|
273
|
+
await (0, user_1.deleteUser)(options);
|
|
274
|
+
await promptContinue();
|
|
275
|
+
break;
|
|
276
|
+
case 'user-share':
|
|
277
|
+
logger_1.default.newline();
|
|
278
|
+
await (0, user_1.showUserShare)(options);
|
|
279
|
+
await promptContinue();
|
|
280
|
+
break;
|
|
281
|
+
default:
|
|
282
|
+
logger_1.default.warn(`未知选项: ${selection}`);
|
|
283
|
+
break;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Prompt user to continue
|
|
289
|
+
*/
|
|
290
|
+
async function promptContinue() {
|
|
291
|
+
await (0, prompts_1.confirm)({
|
|
292
|
+
message: '按 Enter 继续...',
|
|
293
|
+
default: true,
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Handle SIGINT (Ctrl+C)
|
|
298
|
+
*/
|
|
299
|
+
async function handleSigInt() {
|
|
300
|
+
logger_1.default.newline();
|
|
301
|
+
const shouldExit = await (0, prompts_1.confirm)({
|
|
302
|
+
message: chalk_1.default.yellow('⚠️ 确定要退出吗?'),
|
|
303
|
+
default: false,
|
|
304
|
+
});
|
|
305
|
+
return shouldExit;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Main interactive menu loop
|
|
309
|
+
*/
|
|
310
|
+
async function startInteractiveMenu(options) {
|
|
311
|
+
logger_1.default.title('Xray Manager - 交互式管理工具');
|
|
312
|
+
// Setup SIGINT handler
|
|
313
|
+
let sigintHandled = false;
|
|
314
|
+
const sigintHandler = async () => {
|
|
315
|
+
if (sigintHandled)
|
|
316
|
+
return;
|
|
317
|
+
sigintHandled = true;
|
|
318
|
+
const shouldExit = await handleSigInt();
|
|
319
|
+
if (shouldExit) {
|
|
320
|
+
logger_1.default.info('👋 再见!');
|
|
321
|
+
process.exit(exit_codes_1.ExitCode.SUCCESS);
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
sigintHandled = false;
|
|
325
|
+
// Continue with menu
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
process.on('SIGINT', sigintHandler);
|
|
329
|
+
try {
|
|
330
|
+
// Get menu context
|
|
331
|
+
const context = await getMenuContext(options);
|
|
332
|
+
// Main menu loop
|
|
333
|
+
let shouldExit = false;
|
|
334
|
+
while (!shouldExit) {
|
|
335
|
+
logger_1.default.newline();
|
|
336
|
+
logger_1.default.separator();
|
|
337
|
+
// Display context
|
|
338
|
+
const header = formatMenuHeader(context);
|
|
339
|
+
console.log(header);
|
|
340
|
+
logger_1.default.separator();
|
|
341
|
+
logger_1.default.newline();
|
|
342
|
+
// Get menu options
|
|
343
|
+
const menuOptions = getMainMenuOptions();
|
|
344
|
+
// Show menu and get selection
|
|
345
|
+
const selection = await showMenu(menuOptions, chalk_1.default.bold('请选择操作:'));
|
|
346
|
+
// Handle selection
|
|
347
|
+
shouldExit = await handleMenuSelection(selection, options);
|
|
348
|
+
// Update context after each action
|
|
349
|
+
if (!shouldExit) {
|
|
350
|
+
const updatedContext = await getMenuContext(options);
|
|
351
|
+
Object.assign(context, updatedContext);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
logger_1.default.success('感谢使用 Xray Manager!');
|
|
355
|
+
}
|
|
356
|
+
finally {
|
|
357
|
+
// Cleanup
|
|
358
|
+
process.removeListener('SIGINT', sigintHandler);
|
|
359
|
+
menuStack.clear();
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
//# sourceMappingURL=interactive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactive.js","sourceRoot":"","sources":["../../src/commands/interactive.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logs Command Handler
|
|
3
|
+
*
|
|
4
|
+
* Handles log viewing commands (view, follow, filter)
|
|
5
|
+
*
|
|
6
|
+
* @module commands/logs
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Logs command options
|
|
10
|
+
*/
|
|
11
|
+
export interface LogsCommandOptions {
|
|
12
|
+
/** Service name */
|
|
13
|
+
serviceName?: string;
|
|
14
|
+
/** JSON output mode */
|
|
15
|
+
json?: boolean;
|
|
16
|
+
/** Log level filter */
|
|
17
|
+
level?: string;
|
|
18
|
+
/** Time range start */
|
|
19
|
+
since?: string;
|
|
20
|
+
/** Number of lines */
|
|
21
|
+
lines?: number;
|
|
22
|
+
/** Follow mode */
|
|
23
|
+
follow?: boolean;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* View recent logs
|
|
27
|
+
*
|
|
28
|
+
* @param options - Command options
|
|
29
|
+
*/
|
|
30
|
+
export declare function viewLogs(options?: LogsCommandOptions): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Follow logs in real-time
|
|
33
|
+
*
|
|
34
|
+
* @param options - Command options
|
|
35
|
+
*/
|
|
36
|
+
export declare function followLogs(options?: LogsCommandOptions): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Interactive log filtering
|
|
39
|
+
*
|
|
40
|
+
* @param options - Command options
|
|
41
|
+
*/
|
|
42
|
+
export declare function filterLogs(options?: LogsCommandOptions): Promise<void>;
|
|
43
|
+
//# sourceMappingURL=logs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logs.d.ts","sourceRoot":"","sources":["../../src/commands/logs.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,mBAAmB;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,uBAAuB;IACvB,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf,uBAAuB;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,uBAAuB;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,sBAAsB;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,kBAAkB;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AA+ED;;;;GAIG;AACH,wBAAsB,QAAQ,CAAC,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuD9E;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsDhF;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiEhF"}
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Logs Command Handler
|
|
4
|
+
*
|
|
5
|
+
* Handles log viewing commands (view, follow, filter)
|
|
6
|
+
*
|
|
7
|
+
* @module commands/logs
|
|
8
|
+
*/
|
|
9
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
10
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
11
|
+
};
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.viewLogs = viewLogs;
|
|
14
|
+
exports.followLogs = followLogs;
|
|
15
|
+
exports.filterLogs = filterLogs;
|
|
16
|
+
const log_manager_1 = require("../services/log-manager");
|
|
17
|
+
const logger_1 = __importDefault(require("../utils/logger"));
|
|
18
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
19
|
+
const prompts_1 = require("@inquirer/prompts");
|
|
20
|
+
/**
|
|
21
|
+
* Get color for log level
|
|
22
|
+
*
|
|
23
|
+
* @param level - Log level
|
|
24
|
+
* @returns Chalk color function
|
|
25
|
+
*/
|
|
26
|
+
function getColorForLevel(level) {
|
|
27
|
+
switch (level.toLowerCase()) {
|
|
28
|
+
case 'emergency':
|
|
29
|
+
case 'alert':
|
|
30
|
+
case 'critical':
|
|
31
|
+
case 'error':
|
|
32
|
+
return chalk_1.default.red;
|
|
33
|
+
case 'warning':
|
|
34
|
+
return chalk_1.default.yellow;
|
|
35
|
+
case 'notice':
|
|
36
|
+
return chalk_1.default.cyan;
|
|
37
|
+
case 'info':
|
|
38
|
+
return chalk_1.default.white;
|
|
39
|
+
case 'debug':
|
|
40
|
+
return chalk_1.default.gray;
|
|
41
|
+
default:
|
|
42
|
+
return chalk_1.default.white;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Get emoji for log level
|
|
47
|
+
*
|
|
48
|
+
* @param level - Log level
|
|
49
|
+
* @returns Emoji string
|
|
50
|
+
*/
|
|
51
|
+
function getEmojiForLevel(level) {
|
|
52
|
+
switch (level.toLowerCase()) {
|
|
53
|
+
case 'emergency':
|
|
54
|
+
case 'alert':
|
|
55
|
+
return '🚨';
|
|
56
|
+
case 'critical':
|
|
57
|
+
case 'error':
|
|
58
|
+
return '❌';
|
|
59
|
+
case 'warning':
|
|
60
|
+
return '⚠️';
|
|
61
|
+
case 'notice':
|
|
62
|
+
return '📢';
|
|
63
|
+
case 'info':
|
|
64
|
+
return 'ℹ️';
|
|
65
|
+
case 'debug':
|
|
66
|
+
return '🐛';
|
|
67
|
+
default:
|
|
68
|
+
return '📄';
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Format log entry for display
|
|
73
|
+
*
|
|
74
|
+
* @param entry - Log entry
|
|
75
|
+
* @returns Formatted string
|
|
76
|
+
*/
|
|
77
|
+
function formatLogEntry(entry) {
|
|
78
|
+
const colorFn = getColorForLevel(entry.level);
|
|
79
|
+
const emoji = getEmojiForLevel(entry.level);
|
|
80
|
+
const timestamp = entry.timestamp.toLocaleString('zh-CN', {
|
|
81
|
+
year: 'numeric',
|
|
82
|
+
month: '2-digit',
|
|
83
|
+
day: '2-digit',
|
|
84
|
+
hour: '2-digit',
|
|
85
|
+
minute: '2-digit',
|
|
86
|
+
second: '2-digit',
|
|
87
|
+
});
|
|
88
|
+
const level = entry.level.toUpperCase().padEnd(9);
|
|
89
|
+
return `${chalk_1.default.gray(timestamp)} ${emoji} ${colorFn(level)} ${entry.message}`;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* View recent logs
|
|
93
|
+
*
|
|
94
|
+
* @param options - Command options
|
|
95
|
+
*/
|
|
96
|
+
async function viewLogs(options = {}) {
|
|
97
|
+
try {
|
|
98
|
+
const serviceName = options.serviceName || 'xray';
|
|
99
|
+
const manager = new log_manager_1.LogManager(serviceName);
|
|
100
|
+
// Check journalctl availability
|
|
101
|
+
if (!manager.isJournalctlAvailable()) {
|
|
102
|
+
logger_1.default.error('journalctl 不可用。请确保系统使用 systemd。');
|
|
103
|
+
process.exit(1);
|
|
104
|
+
}
|
|
105
|
+
// Query logs
|
|
106
|
+
const logs = await manager.queryLogs({
|
|
107
|
+
level: options.level,
|
|
108
|
+
since: options.since,
|
|
109
|
+
lines: options.lines || 50,
|
|
110
|
+
});
|
|
111
|
+
if (options.json) {
|
|
112
|
+
console.log(JSON.stringify(logs, null, 2));
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
logger_1.default.newline();
|
|
116
|
+
logger_1.default.separator();
|
|
117
|
+
console.log(chalk_1.default.bold.cyan(`📝 服务日志 (${serviceName})`));
|
|
118
|
+
if (options.level) {
|
|
119
|
+
console.log(chalk_1.default.gray(` 过滤器: 级别 ≥ ${options.level}`));
|
|
120
|
+
}
|
|
121
|
+
if (options.since) {
|
|
122
|
+
console.log(chalk_1.default.gray(` 时间范围: ${options.since} 至今`));
|
|
123
|
+
}
|
|
124
|
+
console.log(chalk_1.default.gray(` 显示: 最近 ${logs.length} 条`));
|
|
125
|
+
logger_1.default.separator();
|
|
126
|
+
logger_1.default.newline();
|
|
127
|
+
if (logs.length === 0) {
|
|
128
|
+
console.log(chalk_1.default.gray(' 没有找到日志'));
|
|
129
|
+
logger_1.default.newline();
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
// Display logs
|
|
133
|
+
for (const log of logs) {
|
|
134
|
+
console.log(formatLogEntry(log));
|
|
135
|
+
}
|
|
136
|
+
logger_1.default.newline();
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
logger_1.default.error(error.message);
|
|
140
|
+
process.exit(1);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Follow logs in real-time
|
|
145
|
+
*
|
|
146
|
+
* @param options - Command options
|
|
147
|
+
*/
|
|
148
|
+
async function followLogs(options = {}) {
|
|
149
|
+
try {
|
|
150
|
+
const serviceName = options.serviceName || 'xray';
|
|
151
|
+
const manager = new log_manager_1.LogManager(serviceName);
|
|
152
|
+
// Check journalctl availability
|
|
153
|
+
if (!manager.isJournalctlAvailable()) {
|
|
154
|
+
logger_1.default.error('journalctl 不可用。请确保系统使用 systemd。');
|
|
155
|
+
process.exit(1);
|
|
156
|
+
}
|
|
157
|
+
logger_1.default.newline();
|
|
158
|
+
logger_1.default.separator();
|
|
159
|
+
console.log(chalk_1.default.bold.cyan(`📝 实时日志 (${serviceName})`));
|
|
160
|
+
if (options.level) {
|
|
161
|
+
console.log(chalk_1.default.gray(` 过滤器: 级别 ≥ ${options.level}`));
|
|
162
|
+
}
|
|
163
|
+
console.log(chalk_1.default.gray(' 按 Ctrl+C 停止'));
|
|
164
|
+
logger_1.default.separator();
|
|
165
|
+
logger_1.default.newline();
|
|
166
|
+
// Follow logs
|
|
167
|
+
const followProcess = await manager.followLogs({
|
|
168
|
+
level: options.level,
|
|
169
|
+
lines: options.lines || 10,
|
|
170
|
+
}, (entry) => {
|
|
171
|
+
console.log(formatLogEntry(entry));
|
|
172
|
+
});
|
|
173
|
+
// Handle Ctrl+C
|
|
174
|
+
const sigintHandler = () => {
|
|
175
|
+
logger_1.default.newline();
|
|
176
|
+
logger_1.default.info('停止日志跟踪...');
|
|
177
|
+
followProcess.kill();
|
|
178
|
+
process.exit(0);
|
|
179
|
+
};
|
|
180
|
+
process.on('SIGINT', sigintHandler);
|
|
181
|
+
// Wait for process to exit
|
|
182
|
+
await new Promise((resolve) => {
|
|
183
|
+
followProcess.process.on('close', resolve);
|
|
184
|
+
});
|
|
185
|
+
process.removeListener('SIGINT', sigintHandler);
|
|
186
|
+
}
|
|
187
|
+
catch (error) {
|
|
188
|
+
logger_1.default.error(error.message);
|
|
189
|
+
process.exit(1);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Interactive log filtering
|
|
194
|
+
*
|
|
195
|
+
* @param options - Command options
|
|
196
|
+
*/
|
|
197
|
+
async function filterLogs(options = {}) {
|
|
198
|
+
try {
|
|
199
|
+
logger_1.default.newline();
|
|
200
|
+
console.log(chalk_1.default.bold('🔍 日志过滤'));
|
|
201
|
+
logger_1.default.newline();
|
|
202
|
+
// Select log level
|
|
203
|
+
const levelChoice = await (0, prompts_1.select)({
|
|
204
|
+
message: '选择日志级别:',
|
|
205
|
+
choices: [
|
|
206
|
+
{ name: '🚨 Emergency (紧急)', value: 'emergency' },
|
|
207
|
+
{ name: '🔴 Alert (警报)', value: 'alert' },
|
|
208
|
+
{ name: '❗ Critical (严重)', value: 'critical' },
|
|
209
|
+
{ name: '❌ Error (错误)', value: 'error' },
|
|
210
|
+
{ name: '⚠️ Warning (警告)', value: 'warning' },
|
|
211
|
+
{ name: '📢 Notice (通知)', value: 'notice' },
|
|
212
|
+
{ name: 'ℹ️ Info (信息)', value: 'info' },
|
|
213
|
+
{ name: '🐛 Debug (调试)', value: 'debug' },
|
|
214
|
+
{ name: chalk_1.default.gray('不过滤'), value: 'none' },
|
|
215
|
+
],
|
|
216
|
+
});
|
|
217
|
+
// Select time range
|
|
218
|
+
const timeChoice = await (0, prompts_1.select)({
|
|
219
|
+
message: '选择时间范围:',
|
|
220
|
+
choices: [
|
|
221
|
+
{ name: '最近 1 小时', value: '1 hour ago' },
|
|
222
|
+
{ name: '最近 3 小时', value: '3 hours ago' },
|
|
223
|
+
{ name: '最近 6 小时', value: '6 hours ago' },
|
|
224
|
+
{ name: '最近 12 小时', value: '12 hours ago' },
|
|
225
|
+
{ name: '今天', value: 'today' },
|
|
226
|
+
{ name: '昨天', value: 'yesterday' },
|
|
227
|
+
{ name: '最近 7 天', value: '7 days ago' },
|
|
228
|
+
{ name: chalk_1.default.gray('自定义'), value: 'custom' },
|
|
229
|
+
{ name: chalk_1.default.gray('不限制'), value: 'none' },
|
|
230
|
+
],
|
|
231
|
+
});
|
|
232
|
+
let since = timeChoice === 'none' ? undefined : timeChoice;
|
|
233
|
+
if (timeChoice === 'custom') {
|
|
234
|
+
since = await (0, prompts_1.input)({
|
|
235
|
+
message: '请输入时间范围 (例如: "2024-01-01", "1 week ago"):',
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
// Select number of lines
|
|
239
|
+
const linesStr = await (0, prompts_1.input)({
|
|
240
|
+
message: '显示多少条日志? (默认 50):',
|
|
241
|
+
default: '50',
|
|
242
|
+
});
|
|
243
|
+
const lines = parseInt(linesStr, 10);
|
|
244
|
+
// Query logs
|
|
245
|
+
await viewLogs({
|
|
246
|
+
...options,
|
|
247
|
+
level: levelChoice === 'none' ? undefined : levelChoice,
|
|
248
|
+
since,
|
|
249
|
+
lines,
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
catch (error) {
|
|
253
|
+
logger_1.default.error(error.message);
|
|
254
|
+
process.exit(1);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
//# sourceMappingURL=logs.js.map
|