webtty 1.1.1 → 1.2.0

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
@@ -1,6 +1,14 @@
1
+ <img src="assets/social-preview.png" width="600">
2
+
1
3
  # webtty
2
4
 
3
- A web TTY for running CLI/TUI applications in a browser tab, across platforms.
5
+ Terminal UI in the browser. Run CLI/TUI applications in a browser tab, across platforms.
6
+
7
+ ```sh
8
+ npx webtty run # start server + open a terminal in the browser
9
+ npx webtty ls # list sessions
10
+ npx webtty help # show all commands
11
+ ```
4
12
 
5
13
  ## Debugging
6
14
 
package/dist/cli/index.js CHANGED
@@ -2157,7 +2157,7 @@ var {
2157
2157
  } = import__.default;
2158
2158
 
2159
2159
  // src/cli/http.ts
2160
- import { spawn } from "node:child_process";
2160
+ import * as childProcess from "node:child_process";
2161
2161
  import fs from "node:fs";
2162
2162
  import path from "node:path";
2163
2163
  import { fileURLToPath } from "node:url";
@@ -2173,7 +2173,7 @@ async function isServerRunning() {
2173
2173
  return false;
2174
2174
  }
2175
2175
  }
2176
- async function startServer() {
2176
+ async function startServer(timeoutMs = 1e4, _spawn = childProcess.spawn) {
2177
2177
  const isBun = typeof globalThis.Bun !== "undefined";
2178
2178
  const isTs = isBun && __filename2.endsWith(".ts");
2179
2179
  const serverEntry = path.resolve(__dirname2, isTs ? "../server/index.ts" : "../server/index.js");
@@ -2181,13 +2181,13 @@ async function startServer() {
2181
2181
  console.error(`webtty: server entry not found at ${serverEntry}`);
2182
2182
  process.exit(1);
2183
2183
  }
2184
- const child = spawn(process.execPath, [serverEntry], {
2184
+ const child = _spawn(process.execPath, [serverEntry], {
2185
2185
  detached: true,
2186
2186
  stdio: "ignore",
2187
2187
  env: { ...process.env, PORT: String(PORT) }
2188
2188
  });
2189
2189
  child.unref();
2190
- const deadline = Date.now() + 1e4;
2190
+ const deadline = Date.now() + timeoutMs;
2191
2191
  while (Date.now() < deadline) {
2192
2192
  if (await isServerRunning())
2193
2193
  return;
@@ -2196,14 +2196,32 @@ async function startServer() {
2196
2196
  console.error("webtty: server did not start in time");
2197
2197
  process.exit(1);
2198
2198
  }
2199
- function openBrowser(url) {
2199
+ async function stopServer(baseUrl = BASE_URL, timeoutMs = 5000) {
2200
+ try {
2201
+ const res = await fetch(`${baseUrl}/api/server/stop`, { method: "POST" });
2202
+ if (!res.ok)
2203
+ return false;
2204
+ const deadline = Date.now() + timeoutMs;
2205
+ while (Date.now() < deadline) {
2206
+ if (!await isServerRunning())
2207
+ return true;
2208
+ await new Promise((r) => setTimeout(r, 100));
2209
+ }
2210
+ return false;
2211
+ } catch {
2212
+ return false;
2213
+ }
2214
+ }
2215
+ function openBrowser(url, _spawn = childProcess.spawn) {
2200
2216
  if (process.env.WEBTTY_NO_OPEN === "1")
2201
2217
  return;
2218
+ if (false)
2219
+ ;
2202
2220
  if (process.platform === "win32") {
2203
- spawn("cmd.exe", ["/c", "start", "", url], { detached: true, stdio: "ignore" }).unref();
2221
+ _spawn("cmd.exe", ["/c", "start", "", url], { detached: true, stdio: "ignore" }).unref();
2204
2222
  } else {
2205
2223
  const cmd = process.platform === "darwin" ? "open" : "xdg-open";
2206
- spawn(cmd, [url], { detached: true, stdio: "ignore" }).unref();
2224
+ _spawn(cmd, [url], { detached: true, stdio: "ignore" }).unref();
2207
2225
  }
2208
2226
  }
2209
2227
 
@@ -2218,16 +2236,16 @@ function registerCommands(program2) {
2218
2236
  console.log("webtty started");
2219
2237
  });
2220
2238
  program2.command("stop").description("Stop the webtty server").action(async () => {
2221
- try {
2222
- const res = await fetch(`${BASE_URL}/api/server/stop`, { method: "POST" });
2223
- if (res.ok) {
2224
- console.log("webtty stopped");
2225
- } else {
2226
- console.error(`webtty stop failed (status: ${res.status})`);
2227
- process.exit(1);
2228
- }
2229
- } catch {
2239
+ if (!await isServerRunning()) {
2230
2240
  console.log("webtty is not running");
2241
+ return;
2242
+ }
2243
+ const ok = await stopServer();
2244
+ if (ok) {
2245
+ console.log("webtty stopped");
2246
+ } else {
2247
+ console.error("webtty stop failed");
2248
+ process.exit(1);
2231
2249
  }
2232
2250
  });
2233
2251
  program2.command("ls").description("List all sessions").action(async () => {
@@ -2333,6 +2351,17 @@ function registerCommands(program2) {
2333
2351
  process.exit(1);
2334
2352
  }
2335
2353
  });
2354
+ program2.command("restart").description("Restart the webtty server").action(async () => {
2355
+ if (await isServerRunning()) {
2356
+ const ok = await stopServer();
2357
+ if (!ok) {
2358
+ console.error("webtty: failed to stop server");
2359
+ process.exit(1);
2360
+ }
2361
+ }
2362
+ await startServer();
2363
+ console.log("webtty restarted");
2364
+ });
2336
2365
  }
2337
2366
 
2338
2367
  // src/cli/index.ts
@@ -2341,4 +2370,4 @@ program2.name("webtty").description("Web TTY — run terminal sessions in a brow
2341
2370
  registerCommands(program2);
2342
2371
  program2.parse(process.argv);
2343
2372
 
2344
- //# debugId=1C9197F72FC17E7564756E2164756E21
2373
+ //# debugId=1DEC1C353196B21C64756E2164756E21