@usex/mikrotik-mcp 4.11.0 → 4.13.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/dist/cli.js CHANGED
@@ -112,6 +112,7 @@ import {
112
112
  import { existsSync as existsSync2 } from "fs";
113
113
 
114
114
  // src/observability/dashboard.ts
115
+ import { spawn } from "child_process";
115
116
  import { readFileSync as readFileSync2 } from "fs";
116
117
  import { homedir, networkInterfaces } from "os";
117
118
  import { dirname as dirname4, join as join2 } from "path";
@@ -1473,6 +1474,24 @@ var JSON_HEADERS3 = { "content-type": "application/json; charset=utf-8" };
1473
1474
  function json3(body, status = 200) {
1474
1475
  return new Response(JSON.stringify(body), { status, headers: JSON_HEADERS3 });
1475
1476
  }
1477
+ function restartProcess() {
1478
+ let ok = false;
1479
+ try {
1480
+ const child = spawn(process.execPath, process.argv.slice(1), {
1481
+ cwd: process.cwd(),
1482
+ env: { ...process.env, MIKROTIK_RESTART_DELAY_MS: "1500" },
1483
+ detached: true,
1484
+ stdio: "inherit"
1485
+ });
1486
+ child.unref();
1487
+ ok = true;
1488
+ logger.warn("Dashboard requested a restart \u2014 relaunched a fresh server process; this one is exiting.");
1489
+ } catch (e) {
1490
+ logger.error(`Restart relaunch failed: ${e instanceof Error ? e.message : String(e)}. Exiting anyway.`);
1491
+ }
1492
+ setTimeout(() => process.exit(0), 500);
1493
+ return ok;
1494
+ }
1476
1495
  function dashboardHtml() {
1477
1496
  try {
1478
1497
  return readFileSync2(join2(UI_DIST_DIR, "observability.html"), "utf8");
@@ -1774,12 +1793,11 @@ async function configRoutes(req, url, admin) {
1774
1793
  if (p === "/api/reload" && req.method === "POST") {
1775
1794
  const body = await readJson(req);
1776
1795
  if (body?.hard === true) {
1777
- logger.warn("Dashboard requested a HARD restart \u2014 exiting for supervisor respawn");
1778
- setTimeout(() => process.exit(0), 300);
1796
+ const relaunched = restartProcess();
1779
1797
  return json3({
1780
1798
  ok: true,
1781
1799
  mode: "restart",
1782
- note: "Process is exiting now; it only comes back if a supervisor (systemd/docker/pm2/MCP host) respawns it."
1800
+ note: relaunched ? "Restarting now \u2014 a fresh server process was launched and will bind the same port(s) in ~1.5s. Reconnect shortly." : "Could not self-relaunch; the process is exiting. It only comes back if a supervisor respawns it."
1783
1801
  });
1784
1802
  }
1785
1803
  try {
@@ -3259,6 +3277,11 @@ async function main() {
3259
3277
  if (command === "auth-check") {
3260
3278
  process.exit(await authCheck());
3261
3279
  }
3280
+ const restartDelayMs = Number.parseInt(process.env.MIKROTIK_RESTART_DELAY_MS ?? "", 10);
3281
+ if (Number.isFinite(restartDelayMs) && restartDelayMs > 0) {
3282
+ logger.info(`Restart: waiting ${restartDelayMs}ms for the previous process to release its ports\u2026`);
3283
+ await new Promise((resolve) => setTimeout(resolve, restartDelayMs));
3284
+ }
3262
3285
  const cfg = loadConfig();
3263
3286
  setConfig(cfg);
3264
3287
  await printBanner();