tabminal 2.0.10 → 2.0.11

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tabminal",
3
- "version": "2.0.10",
3
+ "version": "2.0.11",
4
4
  "description": "A modern, persistent web terminal with multi-tab support and real-time system monitoring.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/server.mjs CHANGED
@@ -275,6 +275,14 @@ app.use(router.allowedMethods());
275
275
 
276
276
  const httpServer = createServer(app.callback());
277
277
  const wss = new WebSocketServer({ noServer: true, verifyClient });
278
+ const httpConnections = new Set();
279
+
280
+ httpServer.on('connection', (socket) => {
281
+ httpConnections.add(socket);
282
+ socket.on('close', () => {
283
+ httpConnections.delete(socket);
284
+ });
285
+ });
278
286
 
279
287
  httpServer.on('upgrade', (request, socket, head) => {
280
288
  const url = new URL(request.url, `http://${request.headers.host}`);
@@ -370,6 +378,9 @@ function shutdown(signal) {
370
378
  isShuttingDown = true;
371
379
  console.log(`Shutting down (${signal})...`);
372
380
  clearInterval(heartbeatInterval);
381
+ for (const socket of wss.clients) {
382
+ socket.terminate();
383
+ }
373
384
  wss.close();
374
385
  terminalManager.dispose();
375
386
 
@@ -382,6 +393,11 @@ function shutdown(signal) {
382
393
  clearTimeout(forceExitTimer);
383
394
  process.exit(0);
384
395
  });
396
+ httpServer.closeIdleConnections?.();
397
+ httpServer.closeAllConnections?.();
398
+ for (const socket of httpConnections) {
399
+ socket.destroy();
400
+ }
385
401
  }
386
402
 
387
403
  process.on('SIGINT', () => shutdown('SIGINT'));
@@ -9,13 +9,12 @@ import * as persistence from './persistence.mjs';
9
9
  import { config } from './config.mjs';
10
10
 
11
11
  function resolveShell() {
12
- if (process.platform === 'win32') {
13
- return process.env.COMSPEC || 'cmd.exe';
14
- }
15
- // config.shell has already handled process.env.SHELL and TABMINAL_SHELL via config.mjs
16
12
  if (config.shell) {
17
13
  return config.shell;
18
14
  }
15
+ if (process.platform === 'win32') {
16
+ return process.env.COMSPEC || 'cmd.exe';
17
+ }
19
18
  // Try to use Homebrew installed bash if available (newer version)
20
19
  if (fs.existsSync('/opt/homebrew/bin/bash')) {
21
20
  return '/opt/homebrew/bin/bash';
@@ -60,7 +59,12 @@ export class TerminalManager {
60
59
 
61
60
  // Inject shell tools
62
61
  const shellToolsPath = path.join(process.cwd(), 'shell');
63
- env.PATH = `${shellToolsPath}:${env.PATH}`;
62
+ const pathDelimiter = path.delimiter;
63
+ const pathKey = Object.keys(env).find((key) => key.toLowerCase() === 'path') || 'PATH';
64
+ const existingPath = env[pathKey];
65
+ env[pathKey] = existingPath
66
+ ? `${shellToolsPath}${pathDelimiter}${existingPath}`
67
+ : shellToolsPath;
64
68
 
65
69
  let args = [];
66
70
  let initFilePath = null;
@@ -151,14 +155,17 @@ precmd_functions+=(_tabminal_zsh_apply_prompt_marker)
151
155
 
152
156
  let ptyProcess;
153
157
  try {
154
- ptyProcess = pty.spawn(shell, args, {
158
+ const ptyOptions = {
155
159
  name: 'xterm-256color',
156
160
  cols: cols,
157
161
  rows: rows,
158
162
  cwd: initialCwd,
159
- env: env,
160
- encoding: 'utf8'
161
- });
163
+ env: env
164
+ };
165
+ if (process.platform !== 'win32') {
166
+ ptyOptions.encoding = 'utf8';
167
+ }
168
+ ptyProcess = pty.spawn(shell, args, ptyOptions);
162
169
  } catch (err) {
163
170
  const spawnInfo = {
164
171
  shell,
@@ -295,7 +302,11 @@ precmd_functions+=(_tabminal_zsh_apply_prompt_marker)
295
302
  this.disposing = true;
296
303
  for (const session of this.sessions.values()) {
297
304
  try {
298
- session.pty.kill('SIGHUP');
305
+ if (process.platform === 'win32') {
306
+ session.pty.kill();
307
+ } else {
308
+ session.pty.kill('SIGHUP');
309
+ }
299
310
  } catch {
300
311
  // ignore
301
312
  }