mirror of
https://github.com/Nezumi-2711/9router.git
synced 2026-09-22 13:38:31 +00:00
feat: remove check version update feature
This commit is contained in:
@@ -82,7 +82,6 @@ That's it! Start coding with FREE AI models.
|
||||
9router # Start with default settings
|
||||
9router --port 8080 # Custom port
|
||||
9router --no-browser # Don't open browser
|
||||
9router --skip-update # Skip auto-update check
|
||||
9router --help # Show all options
|
||||
```
|
||||
|
||||
|
||||
+9
-142
@@ -3,7 +3,6 @@
|
||||
const { spawn, exec, execSync } = require("child_process");
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const https = require("https");
|
||||
const net = require("net");
|
||||
const os = require("os");
|
||||
|
||||
@@ -26,42 +25,6 @@ function waitServerReady(port, { timeoutMs = 15000, intervalMs = 150 } = {}) {
|
||||
});
|
||||
}
|
||||
|
||||
// Native spinner - no external dependency
|
||||
function createSpinner(text) {
|
||||
const frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
||||
let i = 0;
|
||||
let interval = null;
|
||||
let currentText = text;
|
||||
return {
|
||||
start() {
|
||||
if (process.stdout.isTTY) {
|
||||
process.stdout.write(`\r${frames[0]} ${currentText}`);
|
||||
interval = setInterval(() => {
|
||||
process.stdout.write(`\r${frames[i++ % frames.length]} ${currentText}`);
|
||||
}, 80);
|
||||
}
|
||||
return this;
|
||||
},
|
||||
stop() {
|
||||
if (interval) {
|
||||
clearInterval(interval);
|
||||
interval = null;
|
||||
}
|
||||
if (process.stdout.isTTY) {
|
||||
process.stdout.write("\r\x1b[K");
|
||||
}
|
||||
},
|
||||
succeed(msg) {
|
||||
this.stop();
|
||||
console.log(`✅ ${msg}`);
|
||||
},
|
||||
fail(msg) {
|
||||
this.stop();
|
||||
console.log(`❌ ${msg}`);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const pkg = require("./package.json");
|
||||
const { ensureSqliteRuntime, buildEnvWithRuntime } = require("./hooks/sqliteRuntime");
|
||||
const { ensureTrayRuntime } = require("./hooks/trayRuntime");
|
||||
@@ -77,7 +40,6 @@ try { ensureTrayRuntime({ silent: true }); } catch {}
|
||||
|
||||
// Configuration constants
|
||||
const APP_NAME = pkg.name; // Use from package.json
|
||||
const INSTALL_CMD_LATEST = `npm i -g ${APP_NAME}@latest --prefer-online`;
|
||||
|
||||
const DEFAULT_PORT = 20128;
|
||||
const DEFAULT_HOST = "0.0.0.0";
|
||||
@@ -106,7 +68,6 @@ const PROCESS_IDENTIFIERS = [
|
||||
let port = DEFAULT_PORT;
|
||||
let host = DEFAULT_HOST;
|
||||
let noBrowser = false;
|
||||
let skipUpdate = false;
|
||||
let showLog = false;
|
||||
let trayMode = false;
|
||||
|
||||
@@ -121,8 +82,6 @@ for (let i = 0; i < args.length; i++) {
|
||||
noBrowser = true;
|
||||
} else if (args[i] === "--log" || args[i] === "-l") {
|
||||
showLog = true;
|
||||
} else if (args[i] === "--skip-update") {
|
||||
skipUpdate = true;
|
||||
} else if (args[i] === "--tray" || args[i] === "-t") {
|
||||
trayMode = true;
|
||||
process.env.TRAY_MODE = "1";
|
||||
@@ -136,7 +95,6 @@ Options:
|
||||
-n, --no-browser Don't open browser automatically
|
||||
-l, --log Show server logs (default: hidden)
|
||||
-t, --tray Run in system tray mode (background)
|
||||
--skip-update Skip auto-update check
|
||||
-h, --help Show this help message
|
||||
-v, --version Show version
|
||||
`);
|
||||
@@ -147,26 +105,9 @@ Options:
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-relaunch after update: detached process has no TTY → fallback to tray
|
||||
if (skipUpdate && !trayMode && !process.stdin.isTTY) {
|
||||
trayMode = true;
|
||||
process.env.TRAY_MODE = "1";
|
||||
}
|
||||
|
||||
// Always use Node.js runtime with absolute path
|
||||
const RUNTIME = process.execPath;
|
||||
|
||||
// Compare semver versions: returns 1 if a > b, -1 if a < b, 0 if equal
|
||||
function compareVersions(a, b) {
|
||||
const partsA = a.split(".").map(Number);
|
||||
const partsB = b.split(".").map(Number);
|
||||
for (let i = 0; i < 3; i++) {
|
||||
if (partsA[i] > partsB[i]) return 1;
|
||||
if (partsA[i] < partsB[i]) return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get app data dir (matches app/src/lib/dataDir.js convention)
|
||||
function getAppDataDir() {
|
||||
return process.platform === "win32"
|
||||
@@ -437,55 +378,6 @@ function isRestrictedEnvironment() {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check if new version available, return latest version or null
|
||||
function checkForUpdate() {
|
||||
return new Promise((resolve) => {
|
||||
if (skipUpdate) {
|
||||
resolve(null);
|
||||
return;
|
||||
}
|
||||
|
||||
const spinner = createSpinner("Checking for updates...").start();
|
||||
let resolved = false;
|
||||
|
||||
const safetyTimeout = setTimeout(() => {
|
||||
if (!resolved) {
|
||||
resolved = true;
|
||||
spinner.stop();
|
||||
resolve(null);
|
||||
}
|
||||
}, 8000);
|
||||
|
||||
const done = (version) => {
|
||||
if (resolved) return;
|
||||
resolved = true;
|
||||
clearTimeout(safetyTimeout);
|
||||
spinner.stop();
|
||||
resolve(version);
|
||||
};
|
||||
|
||||
const req = https.get(`https://registry.npmjs.org/${pkg.name}/latest`, { timeout: 3000 }, (res) => {
|
||||
let data = "";
|
||||
res.on("data", chunk => data += chunk);
|
||||
res.on("end", () => {
|
||||
try {
|
||||
const latest = JSON.parse(data);
|
||||
if (latest.version && compareVersions(latest.version, pkg.version) > 0) {
|
||||
done(latest.version);
|
||||
} else {
|
||||
done(null);
|
||||
}
|
||||
} catch (e) {
|
||||
done(null);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
req.on("error", () => done(null));
|
||||
req.on("timeout", () => { req.destroy(); done(null); });
|
||||
});
|
||||
}
|
||||
|
||||
// Open browser
|
||||
function openBrowser(url) {
|
||||
const platform = process.platform;
|
||||
@@ -520,14 +412,12 @@ if (!fs.existsSync(serverPath)) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Start server immediately; run update check in parallel (not on the critical path).
|
||||
const updatePromise = checkForUpdate();
|
||||
killAllAppProcesses(port)
|
||||
.then(() => killProcessOnPort(port))
|
||||
.then(() => startServer(updatePromise));
|
||||
.then(() => startServer());
|
||||
|
||||
// Show interface selection menu
|
||||
async function showInterfaceMenu(latestVersion) {
|
||||
async function showInterfaceMenu() {
|
||||
const { selectMenu } = require("./src/cli/utils/input");
|
||||
const { clearScreen } = require("./src/cli/utils/display");
|
||||
const { getEndpoint } = require("./src/cli/utils/endpoint");
|
||||
@@ -549,10 +439,6 @@ async function showInterfaceMenu(latestVersion) {
|
||||
|
||||
const menuItems = [];
|
||||
|
||||
if (latestVersion) {
|
||||
menuItems.push({ label: `Update to v${latestVersion} (current: v${pkg.version})`, icon: "⬆" });
|
||||
}
|
||||
|
||||
menuItems.push(
|
||||
{ label: "Web UI (Open in Browser)", icon: "🌐" },
|
||||
{ label: "Terminal UI (Interactive CLI)", icon: "💻" },
|
||||
@@ -562,21 +448,16 @@ async function showInterfaceMenu(latestVersion) {
|
||||
|
||||
const selected = await selectMenu(`Choose Interface (v${pkg.version})`, menuItems, 0, subtitle);
|
||||
|
||||
const offset = latestVersion ? 1 : 0;
|
||||
|
||||
if (latestVersion && selected === 0) return "update";
|
||||
if (selected === offset) return "web";
|
||||
if (selected === offset + 1) return "terminal";
|
||||
if (selected === offset + 2) return "hide";
|
||||
if (selected === 0) return "web";
|
||||
if (selected === 1) return "terminal";
|
||||
if (selected === 2) return "hide";
|
||||
return "exit";
|
||||
}
|
||||
|
||||
const MAX_RESTARTS = 2;
|
||||
const RESTART_RESET_MS = 30000; // Reset counter if alive > 30s
|
||||
|
||||
function startServer(updatePromise) {
|
||||
// Accept either a Promise (parallel update check) or a resolved value.
|
||||
const latestVersionPromise = Promise.resolve(updatePromise);
|
||||
function startServer() {
|
||||
const displayHost = getDisplayHost();
|
||||
const url = `http://${displayHost}:${port}/dashboard`;
|
||||
// Surface real network exposure when bound to all interfaces (default 0.0.0.0).
|
||||
@@ -708,28 +589,14 @@ function startServer(updatePromise) {
|
||||
|
||||
// Wait for server to be ready, then show interface menu loop + tray
|
||||
waitServerReady(port).then(async () => {
|
||||
// Resolve parallel update check (already running); don't block server start on it.
|
||||
const latestVersion = await latestVersionPromise;
|
||||
// Start tray icon alongside TUI
|
||||
initTrayIcon();
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
const choice = await showInterfaceMenu(latestVersion);
|
||||
const choice = await showInterfaceMenu();
|
||||
|
||||
if (choice === "update") {
|
||||
isShuttingDown = true;
|
||||
const { clearScreen } = require("./src/cli/utils/display");
|
||||
clearScreen();
|
||||
console.log(`\n⬆ Update v${pkg.version} → v${latestVersion}\n`);
|
||||
console.log(`Run this after exit:\n`);
|
||||
console.log(` \x1b[33m${INSTALL_CMD_LATEST}\x1b[0m\n`);
|
||||
cleanup();
|
||||
await killAllAppProcesses(port);
|
||||
await killProcessOnPort(port);
|
||||
setTimeout(() => process.exit(0), 200);
|
||||
return;
|
||||
} else if (choice === "web") {
|
||||
if (choice === "web") {
|
||||
openBrowser(url);
|
||||
// Wait for user to come back
|
||||
const { pause } = require("./src/cli/utils/input");
|
||||
@@ -767,7 +634,7 @@ function startServer(updatePromise) {
|
||||
// Windows/Linux: spawn detached bgProcess (systray works fine in child)
|
||||
console.log(`\n⏳ Starting background process... (tray icon will appear in ~3s)`);
|
||||
|
||||
const bgProcess = spawn(process.execPath, [__filename, "--tray", "--skip-update", "-p", port.toString()], {
|
||||
const bgProcess = spawn(process.execPath, [__filename, "--tray", "-p", port.toString()], {
|
||||
detached: true,
|
||||
stdio: "ignore",
|
||||
windowsHide: true,
|
||||
|
||||
@@ -248,17 +248,6 @@ if (fs.existsSync(mitmSrc)) {
|
||||
console.log("⏭️ No MITM files found\n");
|
||||
}
|
||||
|
||||
// Step 7b: Copy standalone updater (headless Node process for install progress)
|
||||
console.log("7️⃣ b Copying updater files...");
|
||||
const updaterSrc = path.join(appDir, "src", "lib", "updater");
|
||||
const updaterDest = path.join(cliAppDir, "src", "lib", "updater");
|
||||
if (fs.existsSync(updaterSrc)) {
|
||||
copyRecursive(updaterSrc, updaterDest);
|
||||
console.log("✅ Copied updater files\n");
|
||||
} else {
|
||||
console.log("⏭️ No updater files found\n");
|
||||
}
|
||||
|
||||
// Step 8: Build MITM server (config driven - see app/cli/scripts/buildMitm.js)
|
||||
console.log("8️⃣ Building MITM server...");
|
||||
try {
|
||||
|
||||
@@ -14,9 +14,7 @@ const cliDir = path.resolve(__dirname, "..");
|
||||
const appDir = path.resolve(cliDir, "..");
|
||||
const cliAppDir = process.env.NINEROUTER_CLI_APP_DIR || path.join(cliDir, "app");
|
||||
const cliMitmDir = path.join(cliAppDir, "src", "mitm");
|
||||
// Bundle everything — no externals. This keeps MITM runtime self-contained so
|
||||
// it can be copied to DATA_DIR/runtime/ and spawned from there (escapes
|
||||
// node_modules file locks that block `npm i -g 9router@latest` on Windows).
|
||||
// Bundle everything — no externals. This keeps the MITM runtime self-contained.
|
||||
const EXTERNALS = [];
|
||||
const ENTRIES = ["server.js"];
|
||||
|
||||
|
||||
@@ -170,7 +170,6 @@ function enableMacOS(cliPath) {
|
||||
<string>${nodePath}</string>
|
||||
<string>${routerScript}</string>
|
||||
<string>--tray</string>
|
||||
<string>--skip-update</string>
|
||||
</array>
|
||||
<key>EnvironmentVariables</key>
|
||||
<dict>
|
||||
@@ -249,7 +248,7 @@ function enableWindows(cliPath) {
|
||||
// Run node + cli.js directly, hidden window. Avoids the fragile
|
||||
// `9router.cmd` lookup that depended on the npm prefix path.
|
||||
const vbsContent = `Set WshShell = CreateObject("WScript.Shell")
|
||||
WshShell.Run """${nodePath}"" ""${routerScript}"" --tray --skip-update", 0, False
|
||||
WshShell.Run """${nodePath}"" ""${routerScript}"" --tray", 0, False
|
||||
`;
|
||||
fs.writeFileSync(vbsPath, vbsContent);
|
||||
return true;
|
||||
@@ -282,7 +281,7 @@ function enableLinux(cliPath) {
|
||||
Type=Application
|
||||
Name=9Router
|
||||
Comment=9Router API Proxy
|
||||
Exec=${nodePath} ${routerScript} --tray --skip-update
|
||||
Exec=${nodePath} ${routerScript} --tray
|
||||
Hidden=false
|
||||
NoDisplay=false
|
||||
X-GNOME-Autostart-enabled=true
|
||||
|
||||
Reference in New Issue
Block a user