mirror of
https://github.com/Nezumi-2711/9router.git
synced 2026-09-22 20:00:47 +00:00
chore: add proper-lockfile for safe database read/write operations and implement retry logic for file access
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { exec } from "child_process";
|
||||
import { join, dirname } from "path";
|
||||
|
||||
// Use npm from the same Node.js that runs Next.js — ensures 9remote
|
||||
// lands in the correct global bin (nvm or system, whichever is active)
|
||||
const npmBin = join(dirname(process.execPath), "npm");
|
||||
|
||||
function installPackage() {
|
||||
return new Promise((resolve, reject) => {
|
||||
exec(`"${npmBin}" install -g 9remote`, { windowsHide: true }, (err, stdout, stderr) => {
|
||||
if (err) reject(new Error(stderr || err.message));
|
||||
else resolve(stdout);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export async function POST() {
|
||||
try {
|
||||
await installPackage();
|
||||
return NextResponse.json({ ok: true });
|
||||
} catch (error) {
|
||||
return NextResponse.json({ ok: false, error: error.message }, { status: 500 });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { spawn } from "child_process";
|
||||
import { join, dirname } from "path";
|
||||
import os from "os";
|
||||
import { setRemoteProcess } from "@/lib/9remoteManager";
|
||||
|
||||
const bin9remote = join(dirname(process.execPath), "9remote");
|
||||
|
||||
export async function POST() {
|
||||
try {
|
||||
const nodeDir = dirname(process.execPath);
|
||||
const existingPath = process.env.PATH || "";
|
||||
const path = existingPath.includes(nodeDir)
|
||||
? existingPath
|
||||
: `${nodeDir}:${existingPath}`;
|
||||
|
||||
const env = {
|
||||
HOME: os.homedir(),
|
||||
PATH: path,
|
||||
USER: process.env.USER || process.env.LOGNAME,
|
||||
LANG: process.env.LANG || "en_US.UTF-8",
|
||||
TERM: process.env.TERM || "xterm-256color",
|
||||
TMPDIR: process.env.TMPDIR || os.tmpdir(),
|
||||
SHELL: process.env.SHELL,
|
||||
};
|
||||
const home = os.homedir();
|
||||
|
||||
// Spawn without detached - process will be child of Next.js and receive SIGTERM
|
||||
const child = spawn(bin9remote, ["ui", "--start"], {
|
||||
cwd: home,
|
||||
stdio: "ignore",
|
||||
env,
|
||||
windowsHide: process.platform === "win32",
|
||||
});
|
||||
|
||||
// Store child process for manual cleanup if needed
|
||||
setRemoteProcess(child);
|
||||
|
||||
return NextResponse.json({ ok: true });
|
||||
} catch (error) {
|
||||
return NextResponse.json({ ok: false, error: error.message }, { status: 500 });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { existsSync } from "fs";
|
||||
import { join, dirname } from "path";
|
||||
|
||||
const bin9remote = join(dirname(process.execPath), "9remote");
|
||||
const AGENT_URL = "http://localhost:2208";
|
||||
|
||||
async function isRunning() {
|
||||
try {
|
||||
const res = await fetch(`${AGENT_URL}/api/health`, {
|
||||
signal: AbortSignal.timeout(1500),
|
||||
});
|
||||
return res.ok;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export async function GET() {
|
||||
const running = await isRunning();
|
||||
if (running) return NextResponse.json({ installed: true, running: true });
|
||||
|
||||
const installed = existsSync(bin9remote);
|
||||
return NextResponse.json({ installed, running: false });
|
||||
}
|
||||
Reference in New Issue
Block a user