livedesk 0.1.248 → 0.1.249

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/README.md CHANGED
@@ -13,6 +13,13 @@ This starts the LiveDesk Hub, opens the local screen wall, and accepts clients.
13
13
  The Hub UI/API listens on `127.0.0.1` by default while the client endpoint
14
14
  continues to listen on the LAN.
15
15
 
16
+ On startup, the launcher checks the Hub ports (`5179` and `5197`). It stops
17
+ only a stale process whose command line identifies it as a LiveDesk Hub, waits
18
+ for both ports to be released, and then starts the new Hub. An unrelated
19
+ process is preserved and reported instead of being terminated; use `--port`,
20
+ `--remote-port`, or stop that process manually. Pass `--no-clean` to disable
21
+ the startup cleanup explicitly.
22
+
16
23
  ## Client
17
24
 
18
25
  ```powershell
package/bin/livedesk.js CHANGED
@@ -222,21 +222,58 @@ async function stopProcessesOnPorts(ports) {
222
222
  const script = [
223
223
  '$ErrorActionPreference = "SilentlyContinue";',
224
224
  `$ports = @(${uniquePorts.join(',')});`,
225
- '$owners = foreach ($port in $ports) {',
226
- ' Get-NetTCPConnection -LocalPort $port -ErrorAction SilentlyContinue | Select-Object -ExpandProperty OwningProcess -Unique',
227
- '}',
228
- '$owners = $owners | Where-Object { $_ -and $_ -ne $PID } | Sort-Object -Unique;',
229
- 'foreach ($owner in $owners) {',
230
- ' $proc = Get-Process -Id $owner -ErrorAction SilentlyContinue;',
231
- ' if ($proc) {',
232
- ' Write-Output "$($proc.Id):$($proc.ProcessName)";',
233
- ' Stop-Process -Id $owner -Force -ErrorAction SilentlyContinue;',
225
+ `$currentNodePid = ${process.pid};`,
226
+ '$records = foreach ($port in $ports) {',
227
+ ' $connections = @(Get-NetTCPConnection -LocalPort $port -State Listen -ErrorAction SilentlyContinue | Where-Object { $_.OwningProcess -and $_.OwningProcess -ne $currentNodePid });',
228
+ ' foreach ($connection in $connections) {',
229
+ ' $owner = [int]$connection.OwningProcess;',
230
+ ' $proc = Get-CimInstance Win32_Process -Filter "ProcessId = $owner" -ErrorAction SilentlyContinue;',
231
+ ' $processName = if ($proc) { [string]$proc.Name } else { "" };',
232
+ ' $commandLine = if ($proc) { [string]$proc.CommandLine } else { "" };',
233
+ ' $knownLiveDesk = $commandLine -match "(?i)(?:livedesk|@livedesk).*hub[\\\\/].*server\\.js";',
234
+ ' [pscustomobject]@{ Port = [int]$port; Pid = $owner; ProcessName = $processName; CommandLine = $commandLine; KnownLiveDesk = [bool]$knownLiveDesk; Action = "preserved" }',
234
235
  ' }',
235
- '}'
236
+ '}',
237
+ '$records = @($records | Sort-Object Port,Pid -Unique);',
238
+ 'foreach ($record in @($records | Where-Object { $_.KnownLiveDesk })) {',
239
+ ' Stop-Process -Id $record.Pid -Force -ErrorAction SilentlyContinue;',
240
+ ' $record.Action = "stopped";',
241
+ '}',
242
+ '$deadline = (Get-Date).ToUniversalTime().AddMilliseconds(3000);',
243
+ 'do {',
244
+ ' $busyPorts = @($ports | Where-Object { Get-NetTCPConnection -LocalPort $_ -State Listen -ErrorAction SilentlyContinue });',
245
+ ' if ($busyPorts.Count -eq 0 -or (Get-Date).ToUniversalTime() -ge $deadline) { break }',
246
+ ' Start-Sleep -Milliseconds 100;',
247
+ '} while ($true);',
248
+ '$busyPortNumbers = @($busyPorts | Select-Object -ExpandProperty LocalPort -Unique);',
249
+ 'foreach ($record in $records) {',
250
+ ' $record.PortAvailable = $busyPortNumbers -notcontains $record.Port;',
251
+ '}',
252
+ '$records | ConvertTo-Json -Compress'
236
253
  ].join(' ');
237
254
  const result = await runQuiet('powershell.exe', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-Command', script]);
255
+ if (!result.ok && !result.stdout) {
256
+ throw new Error(`Could not inspect existing LiveDesk Hub ports: ${result.stderr || result.error?.message || 'PowerShell failed'}`);
257
+ }
258
+ let records = [];
238
259
  if (result.stdout) {
239
- console.log(`Restarting LiveDesk Hub. Cleared port owner(s): ${result.stdout.replace(/\r?\n/g, ', ')}`);
260
+ try {
261
+ const parsed = JSON.parse(result.stdout);
262
+ records = Array.isArray(parsed) ? parsed : [parsed];
263
+ } catch {
264
+ throw new Error(`Could not parse existing LiveDesk Hub port state: ${result.stdout}`);
265
+ }
266
+ }
267
+ const stopped = records.filter(record => record?.Action === 'stopped');
268
+ const preserved = records.filter(record => record?.Action !== 'stopped');
269
+ if (stopped.length > 0) {
270
+ const summary = stopped.map(record => `${record.Pid}:${record.ProcessName || 'node'}@${record.Port}`).join(', ');
271
+ console.log(`Restarting LiveDesk Hub. Stopped stale LiveDesk owner(s): ${summary}`);
272
+ }
273
+ const blocked = records.filter(record => record?.PortAvailable !== true);
274
+ if (blocked.length > 0) {
275
+ const summary = blocked.map(record => `${record.Pid}:${record.ProcessName || 'unknown'}@${record.Port}`).join(', ');
276
+ throw new Error(`LiveDesk Hub port(s) already in use by an unrelated process: ${summary}. Use --port/--remote-port or stop that process manually.`);
240
277
  }
241
278
  return;
242
279
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "livedesk",
3
- "version": "0.1.248",
3
+ "version": "0.1.249",
4
4
  "description": "LiveDesk Hub and client launcher",
5
5
  "type": "module",
6
6
  "bin": {