server-studio 1.2.3 → 1.2.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/CHANGELOG.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  Notable changes to Server Studio. Dates are release dates.
4
4
 
5
+ ## 1.2.4 — 2026-08-30
6
+
7
+ - **Fixed:** on Windows, stopping a server could kill an unrelated process. The port was matched
8
+ with `findstr :5173`, which also matches `0.0.0.0:51730`, so a longer port sharing the prefix was
9
+ caught too. Reported and patched by @anupamme in #1.
10
+ - `killPort` no longer builds a shell command at all, on any platform. The port was already
11
+ sanitised by `Number()`, so this is hardening rather than a fix.
12
+
5
13
  ## 1.2.3 — 2026-08-30
6
14
 
7
15
  - The badge shown after an update now says **quit & reopen** rather than "restart to finish".
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "server-studio",
3
- "version": "1.2.3",
3
+ "version": "1.2.4",
4
4
  "description": "A tiny dashboard for your local dev servers. One click to run, stop and open them, with one permanent port per project.",
5
5
  "author": "Md Mahdi Hasan",
6
6
  "license": "MIT",
package/src/platform.js CHANGED
@@ -4,7 +4,7 @@
4
4
  const fs = require('fs');
5
5
  const os = require('os');
6
6
  const path = require('path');
7
- const { execFile, exec } = require('child_process');
7
+ const { execFile } = require('child_process');
8
8
 
9
9
  const WIN = process.platform === 'win32';
10
10
  const MAC = process.platform === 'darwin';
@@ -86,15 +86,21 @@ function killPort(port, cb) {
86
86
  if (!p) return cb(new Error('bad port'));
87
87
  if (WIN) {
88
88
  // netstat lists the owning PID in the last column of LISTENING rows.
89
- return exec('netstat -ano -p tcp | findstr LISTENING | findstr :' + p, (err, stdout) => {
89
+ // execFile (no shell) avoids ever building a shell command string from `port`.
90
+ return execFile('netstat', ['-ano', '-p', 'tcp'], (err, stdout) => {
90
91
  const pids = new Set(String(stdout || '').trim().split(/\r?\n/)
92
+ .filter(l => /LISTENING/.test(l) && l.includes(':' + p + ' '))
91
93
  .map(l => l.trim().split(/\s+/).pop())
92
94
  .filter(x => /^\d+$/.test(x) && x !== '0'));
93
95
  if (!pids.size) return cb(null);
94
- exec([...pids].map(id => 'taskkill /PID ' + id + ' /T /F').join(' & '), () => cb(null));
96
+ execFile('taskkill', ['/T', '/F', ...[...pids].flatMap(id => ['/PID', id])], () => cb(null));
95
97
  });
96
98
  }
97
- return exec('lsof -nti tcp:' + p + ' | xargs kill 2>/dev/null', () => cb(null));
99
+ return execFile('lsof', ['-nti', 'tcp:' + p], (err, stdout) => {
100
+ const pids = String(stdout || '').trim().split(/\r?\n/).filter(Boolean);
101
+ if (!pids.length) return cb(null);
102
+ execFile('kill', pids, () => cb(null));
103
+ });
98
104
  }
99
105
 
100
106
  /* ---------- native "choose a folder" dialog ---------- */