opensteer 0.4.4 → 0.4.6

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.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Opensteer
3
- } from "../chunk-2NKR4JZ6.js";
3
+ } from "../chunk-MGZ3QEYT.js";
4
4
  import "../chunk-3H5RRIMZ.js";
5
5
 
6
6
  // src/cli/server.ts
@@ -10,14 +10,14 @@ import { writeFileSync, unlinkSync, existsSync } from "fs";
10
10
  // src/cli/paths.ts
11
11
  import { tmpdir } from "os";
12
12
  import { join } from "path";
13
- function prefix(namespace2) {
14
- return `opensteer-${namespace2}`;
13
+ function prefix(session2) {
14
+ return `opensteer-${session2}`;
15
15
  }
16
- function getSocketPath(namespace2) {
17
- return join(tmpdir(), `${prefix(namespace2)}.sock`);
16
+ function getSocketPath(session2) {
17
+ return join(tmpdir(), `${prefix(session2)}.sock`);
18
18
  }
19
- function getPidPath(namespace2) {
20
- return join(tmpdir(), `${prefix(namespace2)}.pid`);
19
+ function getPidPath(session2) {
20
+ return join(tmpdir(), `${prefix(session2)}.pid`);
21
21
  }
22
22
 
23
23
  // src/cli/commands.ts
@@ -255,6 +255,19 @@ function getCommandHandler(name) {
255
255
  // src/cli/server.ts
256
256
  var instance = null;
257
257
  var launchPromise = null;
258
+ var selectorNamespace = null;
259
+ var requestQueue = Promise.resolve();
260
+ var shuttingDown = false;
261
+ function sanitizeNamespace(value) {
262
+ const trimmed = String(value || "").trim();
263
+ if (!trimmed || trimmed === "." || trimmed === "..") {
264
+ return "default";
265
+ }
266
+ const replaced = trimmed.replace(/[^a-zA-Z0-9_-]+/g, "_");
267
+ const collapsed = replaced.replace(/_+/g, "_");
268
+ const bounded = collapsed.replace(/^_+|_+$/g, "");
269
+ return bounded || "default";
270
+ }
258
271
  function invalidateInstance() {
259
272
  if (!instance) return;
260
273
  instance.close().catch(() => {
@@ -268,13 +281,14 @@ function attachLifecycleListeners(inst) {
268
281
  } catch {
269
282
  }
270
283
  }
271
- var namespace = process.env.OPENSTEER_NAME?.trim();
272
- if (!namespace) {
273
- process.stderr.write("Missing OPENSTEER_NAME environment variable.\n");
284
+ var sessionEnv = process.env.OPENSTEER_SESSION?.trim();
285
+ if (!sessionEnv) {
286
+ process.stderr.write("Missing OPENSTEER_SESSION environment variable.\n");
274
287
  process.exit(1);
275
288
  }
276
- var socketPath = getSocketPath(namespace);
277
- var pidPath = getPidPath(namespace);
289
+ var session = sessionEnv;
290
+ var socketPath = getSocketPath(session);
291
+ var pidPath = getPidPath(session);
278
292
  function cleanup() {
279
293
  try {
280
294
  unlinkSync(socketPath);
@@ -285,14 +299,49 @@ function cleanup() {
285
299
  } catch {
286
300
  }
287
301
  }
302
+ function beginShutdown() {
303
+ if (shuttingDown) return;
304
+ shuttingDown = true;
305
+ cleanup();
306
+ server.close(() => {
307
+ process.exit(0);
308
+ });
309
+ setTimeout(() => {
310
+ process.exit(0);
311
+ }, 250).unref();
312
+ }
288
313
  function sendResponse(socket, response) {
289
314
  try {
290
315
  socket.write(JSON.stringify(response) + "\n");
291
316
  } catch {
292
317
  }
293
318
  }
319
+ function enqueueRequest(request, socket) {
320
+ if (request.command === "ping") {
321
+ void handleRequest(request, socket);
322
+ return;
323
+ }
324
+ requestQueue = requestQueue.then(() => handleRequest(request, socket)).catch(() => {
325
+ });
326
+ }
294
327
  async function handleRequest(request, socket) {
295
328
  const { id, command, args } = request;
329
+ if (command === "ping" && shuttingDown) {
330
+ sendResponse(socket, {
331
+ id,
332
+ ok: false,
333
+ error: `Session '${session}' is shutting down.`
334
+ });
335
+ return;
336
+ }
337
+ if (shuttingDown) {
338
+ sendResponse(socket, {
339
+ id,
340
+ ok: false,
341
+ error: `Session '${session}' is shutting down. Retry your command.`
342
+ });
343
+ return;
344
+ }
296
345
  if (command === "open") {
297
346
  try {
298
347
  const url = args.url;
@@ -300,6 +349,19 @@ async function handleRequest(request, socket) {
300
349
  const connectUrl = args["connect-url"];
301
350
  const channel = args.channel;
302
351
  const profileDir = args["profile-dir"];
352
+ const requestedName = typeof args.name === "string" && args.name.trim().length > 0 ? sanitizeNamespace(args.name) : null;
353
+ if (selectorNamespace && requestedName && requestedName !== selectorNamespace) {
354
+ sendResponse(socket, {
355
+ id,
356
+ ok: false,
357
+ error: `Session '${session}' is already bound to selector namespace '${selectorNamespace}'. Requested '${requestedName}' does not match. Use the same --name for this session or start a different --session.`
358
+ });
359
+ return;
360
+ }
361
+ if (!selectorNamespace) {
362
+ selectorNamespace = requestedName ?? session;
363
+ }
364
+ const activeNamespace = selectorNamespace ?? session;
303
365
  if (instance && !launchPromise) {
304
366
  try {
305
367
  if (instance.page.isClosed()) {
@@ -311,7 +373,7 @@ async function handleRequest(request, socket) {
311
373
  }
312
374
  if (!instance) {
313
375
  instance = new Opensteer({
314
- name: namespace,
376
+ name: activeNamespace,
315
377
  browser: {
316
378
  headless: headless ?? false,
317
379
  connectUrl,
@@ -343,8 +405,9 @@ async function handleRequest(request, socket) {
343
405
  ok: true,
344
406
  result: {
345
407
  url: instance.page.url(),
346
- sessionId: instance.getRemoteSessionId() ?? void 0,
347
- name: namespace
408
+ session,
409
+ name: activeNamespace,
410
+ remoteSessionId: instance.getRemoteSessionId() ?? void 0
348
411
  }
349
412
  });
350
413
  } catch (err) {
@@ -374,10 +437,7 @@ async function handleRequest(request, socket) {
374
437
  error: err instanceof Error ? err.message : String(err)
375
438
  });
376
439
  }
377
- setTimeout(() => {
378
- cleanup();
379
- process.exit(0);
380
- }, 100);
440
+ beginShutdown();
381
441
  return;
382
442
  }
383
443
  if (command === "ping") {
@@ -388,7 +448,7 @@ async function handleRequest(request, socket) {
388
448
  sendResponse(socket, {
389
449
  id,
390
450
  ok: false,
391
- error: `No browser session in namespace '${namespace}'. Call 'opensteer open --name ${namespace}' first, or use 'opensteer sessions' to list active sessions.`
451
+ error: `No browser session in session '${session}'. Call 'opensteer open --session ${session}' first, or use 'opensteer sessions' to list active sessions.`
392
452
  });
393
453
  return;
394
454
  }
@@ -425,7 +485,7 @@ var server = createServer((socket) => {
425
485
  if (!line.trim()) continue;
426
486
  try {
427
487
  const request = JSON.parse(line);
428
- handleRequest(request, socket);
488
+ enqueueRequest(request, socket);
429
489
  } catch {
430
490
  sendResponse(socket, {
431
491
  id: 0,
@@ -450,6 +510,8 @@ server.on("error", (err) => {
450
510
  process.exit(1);
451
511
  });
452
512
  async function shutdown() {
513
+ if (shuttingDown) return;
514
+ shuttingDown = true;
453
515
  if (instance) {
454
516
  try {
455
517
  await instance.close();
@@ -457,9 +519,13 @@ async function shutdown() {
457
519
  }
458
520
  instance = null;
459
521
  }
460
- server.close();
461
522
  cleanup();
462
- process.exit(0);
523
+ server.close(() => {
524
+ process.exit(0);
525
+ });
526
+ setTimeout(() => {
527
+ process.exit(0);
528
+ }, 250).unref();
463
529
  }
464
530
  process.on("SIGTERM", shutdown);
465
531
  process.on("SIGINT", shutdown);