@woopsy/mcpanel 2.1.4 → 2.1.5

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.
@@ -69,7 +69,7 @@ class CommandRouter {
69
69
  ' /stop - Stop the server gracefully',
70
70
  ' /restart - Restart the server',
71
71
  ' /console - Enter the interactive server console',
72
- ' /log - Open live server logs in a new terminal window',
72
+ ' /log - Stream live server logs in this terminal (read-only)',
73
73
  ' /info - Show server path, type, version and status',
74
74
  ' /sync <path> - Connect a different server folder',
75
75
  ' /properties - Edit server.properties interactively',
@@ -79,6 +79,7 @@ class CommandRouter {
79
79
  ' /tunnel java - Auto-create & start a Java tunnel, returns address',
80
80
  ' /tunnel bedrock - Auto-create & start a Bedrock tunnel, returns address',
81
81
  ' /tunnel status - Check tunnel status, address and latency',
82
+ ' /tunnel log - Stream live playit relay logs in this terminal (read-only)',
82
83
  ' /tunnel stop - Stop the playit tunnel agent',
83
84
  ' /tunnel reset - Clear saved agent secret (re-claim on next tunnel)',
84
85
  '',
package/dist/index.js CHANGED
@@ -169,12 +169,12 @@ const COMMAND_LIST = [
169
169
  '/backup create', '/backup list', '/backup restore',
170
170
  '/plugins list', '/plugins install', '/plugins remove',
171
171
  '/setup',
172
- '/tunnel java', '/tunnel bedrock', '/tunnel status', '/tunnel stop', '/tunnel reset',
172
+ '/tunnel java', '/tunnel bedrock', '/tunnel status', '/tunnel log', '/tunnel stop', '/tunnel reset',
173
173
  '/config', '/clear', '/update', '/tray', '/background', '/exit'
174
174
  ];
175
175
  // Subcommands offered once "<command> " has been typed.
176
176
  const SUBCOMMANDS = {
177
- '/tunnel': ['java', 'bedrock', 'status', 'stop', 'reset'],
177
+ '/tunnel': ['java', 'bedrock', 'status', 'log', 'stop', 'reset'],
178
178
  '/backup': ['create', 'list', 'restore'],
179
179
  '/plugins': ['list', 'install', 'remove'],
180
180
  };
@@ -287,6 +287,17 @@ function exitLogView() {
287
287
  console.log(colors.info('\nReturned to MCPANEL shell.'));
288
288
  promptUser();
289
289
  }
290
+ /**
291
+ * Exits the in-place live tunnel-log view.
292
+ */
293
+ function exitTunnelLogView() {
294
+ if (currentState !== 'TUNNEL_LOG_VIEW')
295
+ return;
296
+ playitManager.unregisterTunnelStream();
297
+ currentState = 'COMMAND';
298
+ console.log(colors.info('\nReturned to MCPANEL shell.'));
299
+ promptUser();
300
+ }
290
301
  /**
291
302
  * Prompt loop builder
292
303
  */
@@ -313,7 +324,7 @@ function promptUser() {
313
324
  rl.setPrompt(colors.bold(`Enter new value for ${propertiesContext.selectedKey}: `));
314
325
  rl.prompt();
315
326
  }
316
- else if (currentState === 'CONSOLE' || currentState === 'LOG_VIEW') {
327
+ else if (currentState === 'CONSOLE' || currentState === 'LOG_VIEW' || currentState === 'TUNNEL_LOG_VIEW') {
317
328
  // Log/console streaming has no custom prompt.
318
329
  rl.setPrompt('');
319
330
  }
@@ -393,8 +404,8 @@ function enterConsoleMode() {
393
404
  });
394
405
  }
395
406
  /**
396
- * /log — opens live server logs in a NEW terminal window (tail -f). Falls back
397
- * to a read-only in-place stream if no terminal emulator could be launched.
407
+ * /log — streams live server logs read-only inside THIS terminal (like
408
+ * /console, but without sending commands). Type /back or /exit to return.
398
409
  */
399
410
  function handleLogCommand() {
400
411
  const server = configManager.getServer();
@@ -403,7 +414,6 @@ function handleLogCommand() {
403
414
  return;
404
415
  }
405
416
  const logPath = logger_1.logger.getServerLogPath(server.name);
406
- // Ensure the file exists so `tail -f` has something to follow.
407
417
  if (!fs.existsSync(logPath)) {
408
418
  try {
409
419
  fs.writeFileSync(logPath, '', 'utf-8');
@@ -411,27 +421,41 @@ function handleLogCommand() {
411
421
  catch { /* ignore */ }
412
422
  }
413
423
  const running = !!processManager.getActiveServer(server.name);
414
- const opened = (0, helpers_1.openTerminalTail)(logPath, `MCPANEL Logs - ${server.name}`);
415
- if (opened) {
416
- console.log(colors.success('Live server logs opened in a new terminal window.'));
417
- if (!running) {
418
- console.log(colors.warning('Server is not running yet — log lines will appear once you /start it.'));
419
- }
420
- return;
421
- }
422
- // Fallback: stream the logs read-only inside this shell.
423
- console.log(colors.warning('Could not open a separate terminal window — showing logs here instead.'));
424
424
  logViewServer = server.name;
425
425
  currentState = 'LOG_VIEW';
426
- console.log(colors.bold(colors.magenta(`\n--- Live Logs: ${server.name} (type /back to return) ---`)));
426
+ console.log(colors.bold(colors.magenta(`\n--- Live Server Logs: ${server.name} ---`)));
427
+ console.log(colors.gray('Read-only. Type /back or /exit to return to MCPANEL shell.\n'));
427
428
  if (fs.existsSync(logPath)) {
428
429
  const logs = fs.readFileSync(logPath, 'utf-8').split('\n');
429
430
  process.stdout.write(logs.slice(-30).join('\n') + '\n');
430
431
  }
432
+ if (!running) {
433
+ console.log(colors.warning('Server is not running yet — lines will appear once you /start it.'));
434
+ }
431
435
  processManager.registerConsoleStream(server.name, (data) => {
432
436
  process.stdout.write(data);
433
437
  });
434
438
  }
439
+ /**
440
+ * /tunnel log — streams the live playit relay log read-only in THIS terminal.
441
+ * Seeds from tunnel.log, then follows the running relay's output. /back to exit.
442
+ */
443
+ function enterTunnelLogView() {
444
+ const logPath = logger_1.logger.getTunnelLogPath();
445
+ currentState = 'TUNNEL_LOG_VIEW';
446
+ console.log(colors.bold(colors.magenta('\n--- Live Tunnel Logs (playit relay) ---')));
447
+ console.log(colors.gray('Read-only. Type /back or /exit to return to MCPANEL shell.\n'));
448
+ if (fs.existsSync(logPath)) {
449
+ const logs = fs.readFileSync(logPath, 'utf-8').split('\n');
450
+ process.stdout.write(logs.slice(-30).join('\n') + '\n');
451
+ }
452
+ if (!playitManager.isAgentRunning()) {
453
+ console.log(colors.warning('Tunnel agent is not running — start it with /tunnel java or /tunnel bedrock.'));
454
+ }
455
+ playitManager.registerTunnelStream((data) => {
456
+ process.stdout.write(data);
457
+ });
458
+ }
435
459
  /**
436
460
  * Command line loop orchestrator
437
461
  */
@@ -531,6 +555,12 @@ async function handleLine(line) {
531
555
  exitLogView();
532
556
  }
533
557
  break;
558
+ case 'TUNNEL_LOG_VIEW':
559
+ // Read-only: only /back or /exit leaves; everything else is ignored.
560
+ if (trimmed === '/exit' || trimmed === '/back') {
561
+ exitTunnelLogView();
562
+ }
563
+ break;
534
564
  }
535
565
  }
536
566
  /**
@@ -688,7 +718,7 @@ async function handleCommandState(line) {
688
718
  case '/tunnel': {
689
719
  const sub = (args[0] || '').toLowerCase();
690
720
  if (!sub) {
691
- console.log(colors.failure('Syntax: /tunnel [java|bedrock|status|stop|reset]'));
721
+ console.log(colors.failure('Syntax: /tunnel [java|bedrock|status|log|stop|reset]'));
692
722
  }
693
723
  else if (sub === 'java' || sub === 'bedrock') {
694
724
  console.log(await router.executeTunnelCreate(sub));
@@ -708,11 +738,14 @@ async function handleCommandState(line) {
708
738
  else if (sub === 'status') {
709
739
  console.log(router.executeTunnelStatus());
710
740
  }
741
+ else if (sub === 'log') {
742
+ enterTunnelLogView();
743
+ }
711
744
  else if (sub === 'reset') {
712
745
  console.log(await router.executeTunnelReset());
713
746
  }
714
747
  else {
715
- console.log(colors.failure('Syntax: /tunnel [java|bedrock|status|stop|reset]'));
748
+ console.log(colors.failure('Syntax: /tunnel [java|bedrock|status|log|stop|reset]'));
716
749
  }
717
750
  break;
718
751
  }
@@ -58,6 +58,8 @@ class PlayitManager {
58
58
  playitProcess = null;
59
59
  claimProcess = null;
60
60
  tunnelStatus;
61
+ // Optional live consumer of relay output, used by the inline `/tunnel log` view.
62
+ tunnelLogCallback = null;
61
63
  constructor(configManager) {
62
64
  this.configManager = configManager;
63
65
  this.tunnelStatus = this.offlineStatus();
@@ -456,11 +458,13 @@ class PlayitManager {
456
458
  const chunk = stripAnsi(d.toString());
457
459
  logger_1.logger.logTunnel(`[stdout] ${chunk.trim()}`);
458
460
  this.parsePlayitOutput(chunk);
461
+ this.tunnelLogCallback?.(chunk);
459
462
  });
460
463
  this.playitProcess.stderr?.on('data', (d) => {
461
464
  const chunk = stripAnsi(d.toString());
462
465
  logger_1.logger.logTunnel(`[stderr] ${chunk.trim()}`);
463
466
  this.parsePlayitOutput(chunk);
467
+ this.tunnelLogCallback?.(chunk);
464
468
  });
465
469
  this.playitProcess.on('close', (code) => {
466
470
  logger_1.logger.logTunnel(`Playit relay exited with code ${code}`);
@@ -502,6 +506,18 @@ class PlayitManager {
502
506
  getStatus() {
503
507
  return this.tunnelStatus;
504
508
  }
509
+ /** True when the relay daemon process is currently running. */
510
+ isAgentRunning() {
511
+ return this.playitProcess !== null;
512
+ }
513
+ /** Streams live relay output (stdout/stderr) to the given consumer. */
514
+ registerTunnelStream(cb) {
515
+ this.tunnelLogCallback = cb;
516
+ }
517
+ /** Stops streaming live relay output. */
518
+ unregisterTunnelStream() {
519
+ this.tunnelLogCallback = null;
520
+ }
505
521
  /** Clears the saved secret so the agent can be re-claimed from scratch. */
506
522
  async resetSecret() {
507
523
  this.stopTunnel();
@@ -77,6 +77,10 @@ exports.logger = {
77
77
  // Return path to the runtime console log for the server
78
78
  return path.join(LOGS_DIR, `server-${serverName.toLowerCase()}.log`);
79
79
  },
80
+ getTunnelLogPath() {
81
+ ensureLogsDirExists();
82
+ return path.join(LOGS_DIR, 'tunnel.log');
83
+ },
80
84
  writeServerConsoleLog(serverName, data) {
81
85
  ensureLogsDirExists();
82
86
  const filePath = path.join(LOGS_DIR, `server-${serverName.toLowerCase()}.log`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@woopsy/mcpanel",
3
- "version": "2.1.4",
3
+ "version": "2.1.5",
4
4
  "description": "MCPANEL — a terminal-based, single-server Minecraft server manager with an Arch/neofetch-style UI, live logs, backups, plugins and Playit.gg tunnels.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {