deckide 3.5.2 → 3.5.4

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/bin/deckide.js CHANGED
@@ -60,38 +60,79 @@ function getRunningPid() {
60
60
  }
61
61
  }
62
62
 
63
- /** Stop server: try HTTP shutdown on common ports, then fall back to killing the PID */
63
+ /** Wait for a process to exit, returns true if it exited */
64
+ function waitForExit(pid, timeoutMs = 5000) {
65
+ const start = Date.now();
66
+ while (Date.now() - start < timeoutMs) {
67
+ try { process.kill(pid, 0); } catch { return true; }
68
+ execSync('sleep 0.2', { stdio: 'ignore' });
69
+ }
70
+ return false;
71
+ }
72
+
73
+ /** Build curl auth flags from settings */
74
+ function getAuthFlags() {
75
+ const s = loadSettings();
76
+ if (s.basicAuthEnabled && s.basicAuthUser && s.basicAuthPassword) {
77
+ return `-u '${s.basicAuthUser}:${s.basicAuthPassword}'`;
78
+ }
79
+ return '';
80
+ }
81
+
82
+ /** Try HTTP shutdown on a specific port */
83
+ function tryHttpShutdown(port) {
84
+ const auth = getAuthFlags();
85
+ try {
86
+ execSync(`curl -sf ${auth} -X POST http://localhost:${port}/api/shutdown -H "Content-Type: application/json" -d '{}'`, {
87
+ timeout: 5000, stdio: 'ignore',
88
+ });
89
+ return true;
90
+ } catch {
91
+ return false;
92
+ }
93
+ }
94
+
95
+ /** Stop server: try HTTP shutdown, SIGTERM, then SIGKILL as last resort */
64
96
  function stopServer() {
65
97
  const port = getPort();
98
+ const pid = getRunningPid();
99
+
66
100
  // Try HTTP shutdown on configured port
67
- if (isServerRunningOnPort(port)) {
68
- try {
69
- execSync(`curl -sf -X POST http://localhost:${port}/api/shutdown -H "Content-Type: application/json" -d '{}'`, {
70
- timeout: 5000, stdio: 'ignore',
71
- });
72
- try { fs.unlinkSync(pidFile); } catch {}
73
- return true;
74
- } catch {}
101
+ if (isServerRunningOnPort(port) && tryHttpShutdown(port)) {
102
+ if (pid) waitForExit(pid, 5000);
103
+ try { fs.unlinkSync(pidFile); } catch {}
104
+ return true;
75
105
  }
106
+
76
107
  // Try default port 8787 if different
77
- if (port !== 8787 && isServerRunningOnPort(8787)) {
78
- try {
79
- execSync(`curl -sf -X POST http://localhost:8787/api/shutdown -H "Content-Type: application/json" -d '{}'`, {
80
- timeout: 5000, stdio: 'ignore',
81
- });
82
- try { fs.unlinkSync(pidFile); } catch {}
83
- return true;
84
- } catch {}
108
+ if (port !== 8787 && isServerRunningOnPort(8787) && tryHttpShutdown(8787)) {
109
+ if (pid) waitForExit(pid, 5000);
110
+ try { fs.unlinkSync(pidFile); } catch {}
111
+ return true;
85
112
  }
113
+
86
114
  // Fall back to killing by PID
87
- const pid = getRunningPid();
88
115
  if (pid) {
89
116
  try {
90
117
  process.kill(pid, 'SIGTERM');
118
+ if (waitForExit(pid, 5000)) {
119
+ try { fs.unlinkSync(pidFile); } catch {}
120
+ return true;
121
+ }
122
+ // SIGKILL as last resort
123
+ process.kill(pid, 'SIGKILL');
124
+ waitForExit(pid, 2000);
91
125
  try { fs.unlinkSync(pidFile); } catch {}
92
126
  return true;
93
- } catch {}
127
+ } catch {
128
+ // Process already gone
129
+ try { fs.unlinkSync(pidFile); } catch {}
130
+ return true;
131
+ }
94
132
  }
133
+
134
+ // No PID but clean up stale pid file
135
+ try { fs.unlinkSync(pidFile); } catch {}
95
136
  return false;
96
137
  }
97
138
 
@@ -413,7 +454,6 @@ const oldPid = getRunningPid();
413
454
  if (oldPid) {
414
455
  console.log('Stopping old server...');
415
456
  stopServer();
416
- await new Promise(r => setTimeout(r, 1000));
417
457
  }
418
458
 
419
459
  // ── Background mode (default) ──
@@ -44,15 +44,6 @@ export function createFileRouter(workspaces) {
44
44
  const rootInput = c.req.query('path') || DEFAULT_ROOT;
45
45
  const requestedPath = c.req.query('subpath') || '';
46
46
  const rootPath = normalizeWorkspacePath(rootInput);
47
- // When workspaces exist, allow browsing within workspaces and ancestor directories
48
- if (workspaces.size > 0) {
49
- const isAllowed = [...workspaces.values()].some(ws => rootPath === ws.path ||
50
- rootPath.startsWith(ws.path + path.sep) ||
51
- ws.path.startsWith(rootPath + path.sep));
52
- if (!isAllowed) {
53
- throw createHttpError('Path outside registered workspaces', 403);
54
- }
55
- }
56
47
  const target = await resolveSafePath(rootPath, requestedPath);
57
48
  const stats = await fs.stat(target);
58
49
  if (!stats.isDirectory()) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deckide",
3
- "version": "3.5.2",
3
+ "version": "3.5.4",
4
4
  "description": "Deck IDE - Browser-based IDE with terminal, file explorer, and git integration",
5
5
  "type": "module",
6
6
  "bin": {