avneesh123 commited on
Commit
3408e9e
Β·
verified Β·
1 Parent(s): a4e8620

Update server.js

Browse files
Files changed (1) hide show
  1. server.js +24 -42
server.js CHANGED
@@ -6,7 +6,6 @@ import { spawn, exec } from "child_process";
6
  import httpProxy from "http-proxy";
7
 
8
  const app = express();
9
-
10
  const PORT = 7860;
11
  const VITE_PORT = 5173;
12
  const PROJECT_DIR = path.join(process.cwd(), "project");
@@ -24,7 +23,6 @@ const FOUNDATION_LOCK = path.join(process.cwd(), ".foundation_lock");
24
  const DEPS_LOCK = path.join(process.cwd(), ".deps_lock");
25
 
26
  /* ================= IDLE TRACKER ================= */
27
-
28
  let lastActivityTime = Date.now();
29
  const IDLE_TIMEOUT = 10 * 60 * 1000; // 10 min koi na ho toh Vite band
30
 
@@ -42,7 +40,6 @@ setInterval(async () => {
42
  }, 60 * 1000);
43
 
44
  /* ================= LOG STREAM ================= */
45
-
46
  let logs = [];
47
  let clients = new Set();
48
  const logHistory = new Map(); // sessionId -> logs
@@ -55,7 +52,6 @@ function pushLog(message, type = "info") {
55
  message,
56
  type // info | error | success | warning | system
57
  };
58
-
59
  logs.push(entry);
60
  if (logs.length > 500) logs.shift();
61
 
@@ -63,13 +59,11 @@ function pushLog(message, type = "info") {
63
  clients.forEach(c => {
64
  try { c.write(payload); } catch { clients.delete(c); }
65
  });
66
-
67
  console.log(`[${type.toUpperCase()}] ${message}`);
68
  }
69
 
70
  /* ================= ALLOWED ORIGINS ================= */
71
  // Sirf yahi domains server access kar sakte hain β€” baaki sab DENIED
72
-
73
  const ALLOWED_ORIGINS = [
74
  // ===== HuggingFace Spaces =====
75
  "https://avneesh123-autodev-mark2.hf.space", // HF Frontend Space
@@ -84,7 +78,6 @@ const ALLOWED_ORIGINS = [
84
  ];
85
 
86
  /* ================= MIDDLEWARE ================= */
87
-
88
  app.use(cors({
89
  origin: (origin, callback) => {
90
  // Origin nahi hai = direct server call = token se protected hai waise bhi
@@ -121,7 +114,6 @@ if (!fs.existsSync(PROJECT_DIR)) {
121
  }
122
 
123
  /* ================= RATE LIMITER ================= */
124
-
125
  const rateLimitMap = new Map();
126
 
127
  function rateLimit(req, res, maxRequests = 30, windowMs = 60000) {
@@ -130,7 +122,6 @@ function rateLimit(req, res, maxRequests = 30, windowMs = 60000) {
130
  const windowStart = now - windowMs;
131
 
132
  if (!rateLimitMap.has(ip)) rateLimitMap.set(ip, []);
133
-
134
  const requests = rateLimitMap.get(ip).filter(t => t > windowStart);
135
  requests.push(now);
136
  rateLimitMap.set(ip, requests);
@@ -154,10 +145,8 @@ setInterval(() => {
154
  }, 300000);
155
 
156
  /* ================= TOKEN SECURITY ================= */
157
-
158
  function verifyToken(req, res) {
159
  const token = req.body?.token || req.query?.token || req.headers?.["x-api-key"];
160
-
161
  if (token !== MASTER_KEY) {
162
  pushLog(`[SECURITY] Unauthorized access attempt from ${req.ip}`, "error");
163
  res.status(403).json({ error: "ACTION_DENIED", message: "Invalid token" });
@@ -167,7 +156,6 @@ function verifyToken(req, res) {
167
  }
168
 
169
  /* ================= SSE LOG STREAM ================= */
170
-
171
  app.get("/api/logs", (req, res) => {
172
  res.setHeader("Content-Type", "text/event-stream");
173
  res.setHeader("Cache-Control", "no-cache");
@@ -198,17 +186,20 @@ app.get("/api/logs", (req, res) => {
198
  });
199
 
200
  /* ================= VITE MANAGER ================= */
201
-
202
  function killVite() {
203
  return new Promise((resolve) => {
204
- if (!viteProcess) return resolve();
205
- pushLog("[SYSTEM] Killing existing Vite process", "system");
206
- viteProcess.kill("SIGTERM");
207
- setTimeout(() => {
208
- if (viteProcess) viteProcess.kill("SIGKILL");
209
  viteProcess = null;
210
- resolve();
211
- }, 2000);
 
 
 
 
 
 
212
  });
213
  }
214
 
@@ -228,7 +219,6 @@ function startVite(forceRestart = false) {
228
  function bootVite() {
229
  pushLog("[SYSTEM] Starting Vite dev server...", "system");
230
  isBooting = true;
231
-
232
  const nodeModules = path.join(PROJECT_DIR, "node_modules");
233
 
234
  const boot = () => {
@@ -242,6 +232,7 @@ function bootVite() {
242
  const msg = d.toString().trim();
243
  if (!msg) return;
244
  pushLog("[VITE] " + msg, "info");
 
245
  if (msg.includes("Local:") || msg.includes("ready in") || msg.includes("localhost")) {
246
  isBooting = false;
247
  buildRetryCount = 0;
@@ -264,7 +255,10 @@ function bootVite() {
264
  if (code !== null && code !== 0 && buildRetryCount < MAX_RETRIES) {
265
  buildRetryCount++;
266
  pushLog(`[SYSTEM] Auto-restarting Vite (attempt ${buildRetryCount}/${MAX_RETRIES})...`, "warning");
267
- setTimeout(() => bootVite(), 3000);
 
 
 
268
  }
269
  });
270
  };
@@ -277,7 +271,6 @@ function bootVite() {
277
  }
278
 
279
  pushLog("[INSTALL] node_modules not found. Installing dependencies...", "system");
280
-
281
  const install = spawn("pnpm", ["install"], {
282
  cwd: PROJECT_DIR,
283
  shell: true
@@ -300,7 +293,6 @@ function bootVite() {
300
  }
301
 
302
  /* ================= STATUS ================= */
303
-
304
  app.get("/api/status", (req, res) => {
305
  res.json({
306
  ready: !!viteProcess && !isBooting,
@@ -314,7 +306,6 @@ app.get("/api/status", (req, res) => {
314
  });
315
 
316
  /* ================= FILE UPDATE ================= */
317
-
318
  app.post("/api/update", async (req, res) => {
319
  if (!verifyToken(req, res)) return;
320
  if (!rateLimit(req, res, 20, 60000)) return;
@@ -324,6 +315,7 @@ app.post("/api/update", async (req, res) => {
324
  // FOUNDATION LOCK β€” agar pehle foundation files aa chuki hain toh dobara mat likho
325
  // Sirf AI ke naye files (fileTree) likhne do β€” foundation skip
326
  const foundationAlreadyWritten = fs.existsSync(FOUNDATION_LOCK);
 
327
  if (foundationAlreadyWritten) {
328
  pushLog("[FOUNDATION] βœ… Foundation already locked β€” skipping base files", "system");
329
  }
@@ -365,7 +357,6 @@ app.post("/api/update", async (req, res) => {
365
  }
366
 
367
  res.json({ success: true, filesUpdated: Object.keys(files || {}).length });
368
-
369
  } catch (e) {
370
  pushLog("[ERROR] File update failed: " + e.message, "error");
371
  res.status(500).json({ error: e.message });
@@ -373,12 +364,10 @@ app.post("/api/update", async (req, res) => {
373
  });
374
 
375
  /* ================= FILE READ ================= */
376
-
377
  app.post("/api/read", async (req, res) => {
378
  if (!verifyToken(req, res)) return;
379
-
380
  const { filePath } = req.body;
381
-
382
  try {
383
  const safePath = path.normalize(filePath).replace(/^(\.\.[\/\\])+/, "");
384
  const fp = path.join(PROJECT_DIR, safePath);
@@ -393,14 +382,12 @@ app.post("/api/read", async (req, res) => {
393
 
394
  const content = await fs.readFile(fp, "utf-8");
395
  res.json({ success: true, content, path: safePath });
396
-
397
  } catch (e) {
398
  res.status(500).json({ error: e.message });
399
  }
400
  });
401
 
402
  /* ================= FILE LIST ================= */
403
-
404
  app.post("/api/files", async (req, res) => {
405
  if (!verifyToken(req, res)) return;
406
 
@@ -410,6 +397,7 @@ app.post("/api/files", async (req, res) => {
410
  const entries = await fs.readdir(dir, { withFileTypes: true });
411
  for (const entry of entries) {
412
  if (["node_modules", ".git", "dist", ".cache"].includes(entry.name)) continue;
 
413
  const relPath = path.join(base, entry.name);
414
  if (entry.isDirectory()) {
415
  const children = await walkDir(path.join(dir, entry.name), relPath);
@@ -427,12 +415,10 @@ app.post("/api/files", async (req, res) => {
427
  });
428
 
429
  /* ================= FILE DELETE ================= */
430
-
431
  app.post("/api/delete", async (req, res) => {
432
  if (!verifyToken(req, res)) return;
433
 
434
  const { filePath } = req.body;
435
-
436
  try {
437
  const safePath = path.normalize(filePath).replace(/^(\.\.[\/\\])+/, "");
438
  const fp = path.join(PROJECT_DIR, safePath);
@@ -444,14 +430,12 @@ app.post("/api/delete", async (req, res) => {
444
  await fs.remove(fp);
445
  pushLog(`[FILES] Deleted: ${safePath}`, "warning");
446
  res.json({ success: true });
447
-
448
  } catch (e) {
449
  res.status(500).json({ error: e.message });
450
  }
451
  });
452
 
453
  /* ================= COMMAND EXEC ================= */
454
-
455
  // Dangerous commands blocked
456
  const BLOCKED_COMMANDS = ["rm -rf /", "mkfs", ":(){ :|:& };:", "shutdown", "reboot", "format"];
457
 
@@ -477,19 +461,18 @@ app.post("/api/execute", (req, res) => {
477
  }, (err, stdout, stderr) => {
478
  const output = stdout || stderr || err?.message || "";
479
  const success = !err;
480
-
481
  if (success) {
482
  pushLog("[TERMINAL] βœ… Done", "success");
483
  } else {
484
  pushLog("[TERMINAL] ❌ " + (err?.message || "Command failed"), "error");
485
  }
486
-
487
  res.json({ success, output, exitCode: err?.code || 0 });
488
  });
489
  });
490
 
491
  /* ================= VITE CONTROL ================= */
492
-
493
  app.post("/api/vite/restart", async (req, res) => {
494
  if (!verifyToken(req, res)) return;
495
  pushLog("[SYSTEM] Manual Vite restart requested", "system");
@@ -505,12 +488,12 @@ app.post("/api/vite/stop", async (req, res) => {
505
  });
506
 
507
  /* ================= PROJECT RESET ================= */
508
-
509
  app.post("/api/reset", async (req, res) => {
510
  if (!verifyToken(req, res)) return;
511
 
512
  try {
513
  pushLog("[SYSTEM] πŸ”„ Resetting project...", "warning");
 
514
  await killVite();
515
  await fs.remove(PROJECT_DIR);
516
  fs.mkdirSync(PROJECT_DIR, { recursive: true });
@@ -527,7 +510,6 @@ app.post("/api/reset", async (req, res) => {
527
  });
528
 
529
  /* ================= HEALTH CHECK ================= */
530
-
531
  app.get("/health", (req, res) => {
532
  res.json({
533
  status: "ok",
@@ -539,7 +521,6 @@ app.get("/health", (req, res) => {
539
  });
540
 
541
  /* ================= PROXY ================= */
542
-
543
  const proxy = httpProxy.createProxyServer({
544
  target: `http://127.0.0.1:${VITE_PORT}`,
545
  changeOrigin: true,
@@ -636,9 +617,11 @@ app.use((req, res, next) => {
636
  // SECRET CHECK β€” sirf root "/" pe check karo
637
  // JS/CSS/assets ko allow karo β€” warna React app toot jaayega
638
  const isRootRequest = req.path === "/" || req.path === "";
 
639
  if (isRootRequest) {
640
  const previewHeader = req.headers["x-autodev-preview"];
641
  const previewParam = req.query["__autodev"];
 
642
  if (previewHeader !== PREVIEW_SECRET && previewParam !== PREVIEW_SECRET) {
643
  pushLog(`[SECURITY] Preview blocked β€” direct access attempt`, "warning");
644
  res.status(403).send(ACCESS_DENIED_PAGE);
@@ -669,7 +652,6 @@ server.on("upgrade", (req, socket, head) => {
669
  });
670
 
671
  /* ================= GRACEFUL SHUTDOWN ================= */
672
-
673
  process.on("SIGTERM", async () => {
674
  pushLog("[SYSTEM] Shutting down gracefully...", "system");
675
  await killVite();
 
6
  import httpProxy from "http-proxy";
7
 
8
  const app = express();
 
9
  const PORT = 7860;
10
  const VITE_PORT = 5173;
11
  const PROJECT_DIR = path.join(process.cwd(), "project");
 
23
  const DEPS_LOCK = path.join(process.cwd(), ".deps_lock");
24
 
25
  /* ================= IDLE TRACKER ================= */
 
26
  let lastActivityTime = Date.now();
27
  const IDLE_TIMEOUT = 10 * 60 * 1000; // 10 min koi na ho toh Vite band
28
 
 
40
  }, 60 * 1000);
41
 
42
  /* ================= LOG STREAM ================= */
 
43
  let logs = [];
44
  let clients = new Set();
45
  const logHistory = new Map(); // sessionId -> logs
 
52
  message,
53
  type // info | error | success | warning | system
54
  };
 
55
  logs.push(entry);
56
  if (logs.length > 500) logs.shift();
57
 
 
59
  clients.forEach(c => {
60
  try { c.write(payload); } catch { clients.delete(c); }
61
  });
 
62
  console.log(`[${type.toUpperCase()}] ${message}`);
63
  }
64
 
65
  /* ================= ALLOWED ORIGINS ================= */
66
  // Sirf yahi domains server access kar sakte hain β€” baaki sab DENIED
 
67
  const ALLOWED_ORIGINS = [
68
  // ===== HuggingFace Spaces =====
69
  "https://avneesh123-autodev-mark2.hf.space", // HF Frontend Space
 
78
  ];
79
 
80
  /* ================= MIDDLEWARE ================= */
 
81
  app.use(cors({
82
  origin: (origin, callback) => {
83
  // Origin nahi hai = direct server call = token se protected hai waise bhi
 
114
  }
115
 
116
  /* ================= RATE LIMITER ================= */
 
117
  const rateLimitMap = new Map();
118
 
119
  function rateLimit(req, res, maxRequests = 30, windowMs = 60000) {
 
122
  const windowStart = now - windowMs;
123
 
124
  if (!rateLimitMap.has(ip)) rateLimitMap.set(ip, []);
 
125
  const requests = rateLimitMap.get(ip).filter(t => t > windowStart);
126
  requests.push(now);
127
  rateLimitMap.set(ip, requests);
 
145
  }, 300000);
146
 
147
  /* ================= TOKEN SECURITY ================= */
 
148
  function verifyToken(req, res) {
149
  const token = req.body?.token || req.query?.token || req.headers?.["x-api-key"];
 
150
  if (token !== MASTER_KEY) {
151
  pushLog(`[SECURITY] Unauthorized access attempt from ${req.ip}`, "error");
152
  res.status(403).json({ error: "ACTION_DENIED", message: "Invalid token" });
 
156
  }
157
 
158
  /* ================= SSE LOG STREAM ================= */
 
159
  app.get("/api/logs", (req, res) => {
160
  res.setHeader("Content-Type", "text/event-stream");
161
  res.setHeader("Cache-Control", "no-cache");
 
186
  });
187
 
188
  /* ================= VITE MANAGER ================= */
 
189
  function killVite() {
190
  return new Promise((resolve) => {
191
+ if (viteProcess) {
192
+ pushLog("[SYSTEM] Killing existing Vite process", "system");
193
+ viteProcess.kill("SIGKILL");
 
 
194
  viteProcess = null;
195
+ }
196
+
197
+ // Pura port clear karo taaki shell command se bache zombies kill ho jayein
198
+ exec("fuser -k 5173/tcp", () => {
199
+ setTimeout(() => {
200
+ resolve();
201
+ }, 1500);
202
+ });
203
  });
204
  }
205
 
 
219
  function bootVite() {
220
  pushLog("[SYSTEM] Starting Vite dev server...", "system");
221
  isBooting = true;
 
222
  const nodeModules = path.join(PROJECT_DIR, "node_modules");
223
 
224
  const boot = () => {
 
232
  const msg = d.toString().trim();
233
  if (!msg) return;
234
  pushLog("[VITE] " + msg, "info");
235
+
236
  if (msg.includes("Local:") || msg.includes("ready in") || msg.includes("localhost")) {
237
  isBooting = false;
238
  buildRetryCount = 0;
 
255
  if (code !== null && code !== 0 && buildRetryCount < MAX_RETRIES) {
256
  buildRetryCount++;
257
  pushLog(`[SYSTEM] Auto-restarting Vite (attempt ${buildRetryCount}/${MAX_RETRIES})...`, "warning");
258
+ setTimeout(() => {
259
+ // Retry se pehle zombie process clear karo
260
+ killVite().then(() => bootVite());
261
+ }, 3000);
262
  }
263
  });
264
  };
 
271
  }
272
 
273
  pushLog("[INSTALL] node_modules not found. Installing dependencies...", "system");
 
274
  const install = spawn("pnpm", ["install"], {
275
  cwd: PROJECT_DIR,
276
  shell: true
 
293
  }
294
 
295
  /* ================= STATUS ================= */
 
296
  app.get("/api/status", (req, res) => {
297
  res.json({
298
  ready: !!viteProcess && !isBooting,
 
306
  });
307
 
308
  /* ================= FILE UPDATE ================= */
 
309
  app.post("/api/update", async (req, res) => {
310
  if (!verifyToken(req, res)) return;
311
  if (!rateLimit(req, res, 20, 60000)) return;
 
315
  // FOUNDATION LOCK β€” agar pehle foundation files aa chuki hain toh dobara mat likho
316
  // Sirf AI ke naye files (fileTree) likhne do β€” foundation skip
317
  const foundationAlreadyWritten = fs.existsSync(FOUNDATION_LOCK);
318
+
319
  if (foundationAlreadyWritten) {
320
  pushLog("[FOUNDATION] βœ… Foundation already locked β€” skipping base files", "system");
321
  }
 
357
  }
358
 
359
  res.json({ success: true, filesUpdated: Object.keys(files || {}).length });
 
360
  } catch (e) {
361
  pushLog("[ERROR] File update failed: " + e.message, "error");
362
  res.status(500).json({ error: e.message });
 
364
  });
365
 
366
  /* ================= FILE READ ================= */
 
367
  app.post("/api/read", async (req, res) => {
368
  if (!verifyToken(req, res)) return;
369
+
370
  const { filePath } = req.body;
 
371
  try {
372
  const safePath = path.normalize(filePath).replace(/^(\.\.[\/\\])+/, "");
373
  const fp = path.join(PROJECT_DIR, safePath);
 
382
 
383
  const content = await fs.readFile(fp, "utf-8");
384
  res.json({ success: true, content, path: safePath });
 
385
  } catch (e) {
386
  res.status(500).json({ error: e.message });
387
  }
388
  });
389
 
390
  /* ================= FILE LIST ================= */
 
391
  app.post("/api/files", async (req, res) => {
392
  if (!verifyToken(req, res)) return;
393
 
 
397
  const entries = await fs.readdir(dir, { withFileTypes: true });
398
  for (const entry of entries) {
399
  if (["node_modules", ".git", "dist", ".cache"].includes(entry.name)) continue;
400
+
401
  const relPath = path.join(base, entry.name);
402
  if (entry.isDirectory()) {
403
  const children = await walkDir(path.join(dir, entry.name), relPath);
 
415
  });
416
 
417
  /* ================= FILE DELETE ================= */
 
418
  app.post("/api/delete", async (req, res) => {
419
  if (!verifyToken(req, res)) return;
420
 
421
  const { filePath } = req.body;
 
422
  try {
423
  const safePath = path.normalize(filePath).replace(/^(\.\.[\/\\])+/, "");
424
  const fp = path.join(PROJECT_DIR, safePath);
 
430
  await fs.remove(fp);
431
  pushLog(`[FILES] Deleted: ${safePath}`, "warning");
432
  res.json({ success: true });
 
433
  } catch (e) {
434
  res.status(500).json({ error: e.message });
435
  }
436
  });
437
 
438
  /* ================= COMMAND EXEC ================= */
 
439
  // Dangerous commands blocked
440
  const BLOCKED_COMMANDS = ["rm -rf /", "mkfs", ":(){ :|:& };:", "shutdown", "reboot", "format"];
441
 
 
461
  }, (err, stdout, stderr) => {
462
  const output = stdout || stderr || err?.message || "";
463
  const success = !err;
464
+
465
  if (success) {
466
  pushLog("[TERMINAL] βœ… Done", "success");
467
  } else {
468
  pushLog("[TERMINAL] ❌ " + (err?.message || "Command failed"), "error");
469
  }
470
+
471
  res.json({ success, output, exitCode: err?.code || 0 });
472
  });
473
  });
474
 
475
  /* ================= VITE CONTROL ================= */
 
476
  app.post("/api/vite/restart", async (req, res) => {
477
  if (!verifyToken(req, res)) return;
478
  pushLog("[SYSTEM] Manual Vite restart requested", "system");
 
488
  });
489
 
490
  /* ================= PROJECT RESET ================= */
 
491
  app.post("/api/reset", async (req, res) => {
492
  if (!verifyToken(req, res)) return;
493
 
494
  try {
495
  pushLog("[SYSTEM] πŸ”„ Resetting project...", "warning");
496
+
497
  await killVite();
498
  await fs.remove(PROJECT_DIR);
499
  fs.mkdirSync(PROJECT_DIR, { recursive: true });
 
510
  });
511
 
512
  /* ================= HEALTH CHECK ================= */
 
513
  app.get("/health", (req, res) => {
514
  res.json({
515
  status: "ok",
 
521
  });
522
 
523
  /* ================= PROXY ================= */
 
524
  const proxy = httpProxy.createProxyServer({
525
  target: `http://127.0.0.1:${VITE_PORT}`,
526
  changeOrigin: true,
 
617
  // SECRET CHECK β€” sirf root "/" pe check karo
618
  // JS/CSS/assets ko allow karo β€” warna React app toot jaayega
619
  const isRootRequest = req.path === "/" || req.path === "";
620
+
621
  if (isRootRequest) {
622
  const previewHeader = req.headers["x-autodev-preview"];
623
  const previewParam = req.query["__autodev"];
624
+
625
  if (previewHeader !== PREVIEW_SECRET && previewParam !== PREVIEW_SECRET) {
626
  pushLog(`[SECURITY] Preview blocked β€” direct access attempt`, "warning");
627
  res.status(403).send(ACCESS_DENIED_PAGE);
 
652
  });
653
 
654
  /* ================= GRACEFUL SHUTDOWN ================= */
 
655
  process.on("SIGTERM", async () => {
656
  pushLog("[SYSTEM] Shutting down gracefully...", "system");
657
  await killVite();