@guanzhu.me/pw-cli 0.0.9 → 0.0.10

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/bin/pw-cli.js CHANGED
@@ -724,14 +724,15 @@ async function main() {
724
724
  }
725
725
 
726
726
  // Ensures a browser is reachable via CDP; if not, spawns playwright-cli open first.
727
+ // Returns the CDP port number.
727
728
  async function ensureBrowserRunning() {
728
729
  const { getPlaywrightCliCdpPort } = require('../src/browser-manager');
729
730
  const { probeCDP } = require('../src/utils');
730
731
  const { readState } = require('../src/state');
731
732
  const cliPort = getPlaywrightCliCdpPort();
732
- if (cliPort && await probeCDP(cliPort, 2000)) return;
733
+ if (cliPort && await probeCDP(cliPort, 2000)) return cliPort;
733
734
  const state = readState();
734
- if (state && await probeCDP(state.port, 2000)) return;
735
+ if (state && await probeCDP(state.port, 2000)) return state.port;
735
736
  // No browser reachable — start one via playwright-cli
736
737
  const { spawnSync } = require('child_process');
737
738
  const res = spawnSync(process.execPath, [cliPath, 'open', '--headed', '--persistent', '--profile', DEFAULT_PROFILE], {
@@ -742,30 +743,31 @@ async function main() {
742
743
  process.stderr.write('pw-cli: failed to open browser\n');
743
744
  process.exit(res.status || 1);
744
745
  }
746
+ // After spawning, re-detect the port
747
+ const newCliPort = getPlaywrightCliCdpPort();
748
+ if (newCliPort) return newCliPort;
749
+ const newState = readState();
750
+ return newState ? newState.port : null;
745
751
  }
746
752
 
747
- // ── goto: navigate the tracked active tab ────────────────────────────────
753
+ // ── goto: navigate the active tab (detected via CDP /json/list) ──────────
748
754
  if (command === 'goto') {
749
755
  const gotoIdx = rawArgv.indexOf('goto');
750
756
  const afterGoto = rawArgv.slice(gotoIdx + 1);
751
757
  const rawUrl = afterGoto.find(a => !a.startsWith('-'));
752
758
  if (rawUrl) {
753
759
  const fullUrl = /^https?:\/\//.test(rawUrl) ? rawUrl : `https://${rawUrl}`;
754
- const activeTabFile = JSON.stringify(path.join(PW_CLI_DIR, 'active-tab.json'));
760
+ const cdpPort = await ensureBrowserRunning();
761
+ const { fetchActivePageUrl } = require('../src/utils');
762
+ const activeUrl = await fetchActivePageUrl(cdpPort);
755
763
  const navCode = `async (page, context) => {
756
764
  const pages = context.pages();
757
765
  let target = pages[pages.length - 1] || page;
758
- try {
759
- const saved = JSON.parse(require('fs').readFileSync(${activeTabFile}, 'utf8'));
760
- const match = pages.find(p => p.url() === saved.url);
761
- if (match) target = match;
762
- } catch {}
766
+ ${activeUrl ? `const match = pages.find(p => p.url() === ${JSON.stringify(activeUrl)});
767
+ if (match) target = match;` : ''}
763
768
  await target.goto(${JSON.stringify(fullUrl)}, { waitUntil: 'domcontentloaded', timeout: 0 });
764
- const resultUrl = target.url();
765
- try { require('fs').writeFileSync(${activeTabFile}, JSON.stringify({ url: resultUrl })); } catch {}
766
- return resultUrl;
769
+ return target.url();
767
770
  }`;
768
- await ensureBrowserRunning();
769
771
  await handleRunCode(['run-code', navCode]);
770
772
  return;
771
773
  }
@@ -812,13 +814,10 @@ async function main() {
812
814
  const rawUrlArg = afterOpen.find(a => !a.startsWith('-') && /^(https?:\/\/|[a-zA-Z0-9]([a-zA-Z0-9-]*\.)+[a-zA-Z]{2,})/.test(a));
813
815
  const urlArg = rawUrlArg && !/^https?:\/\//.test(rawUrlArg) ? `https://${rawUrlArg}` : rawUrlArg;
814
816
  if (urlArg) {
815
- const activeTabFile = JSON.stringify(path.join(PW_CLI_DIR, 'active-tab.json'));
816
817
  const navCode = `async page => {
817
818
  const newPage = await page.context().newPage();
818
819
  await newPage.goto(${JSON.stringify(urlArg)}, { waitUntil: 'domcontentloaded', timeout: 0 });
819
- const resultUrl = newPage.url();
820
- try { require('fs').writeFileSync(${activeTabFile}, JSON.stringify({ url: resultUrl })); } catch {}
821
- return resultUrl;
820
+ return newPage.url();
822
821
  }`;
823
822
  await ensureBrowserRunning();
824
823
  await handleRunCode(['run-code', navCode]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@guanzhu.me/pw-cli",
3
- "version": "0.0.9",
3
+ "version": "0.0.10",
4
4
  "description": "Persistent Playwright browser CLI with headed defaults, profile support, queueing, and script execution",
5
5
  "bin": {
6
6
  "pw-cli": "./bin/pw-cli.js"
package/src/utils.js CHANGED
@@ -52,4 +52,27 @@ function sleep(ms) {
52
52
  return new Promise(r => setTimeout(r, ms));
53
53
  }
54
54
 
55
- module.exports = { readStdin, die, probeCDP, findFreePort, sleep };
55
+ /**
56
+ * Fetch the URL of the most recently active page tab via Chrome's /json/list endpoint.
57
+ * Chrome returns targets ordered by most-recently-activated first.
58
+ * Returns the URL string, or null if no page target found.
59
+ */
60
+ function fetchActivePageUrl(port) {
61
+ return new Promise(resolve => {
62
+ const req = http.get(`http://127.0.0.1:${port}/json/list`, { timeout: 3000 }, res => {
63
+ let data = '';
64
+ res.on('data', chunk => { data += chunk; });
65
+ res.on('end', () => {
66
+ try {
67
+ const targets = JSON.parse(data);
68
+ const page = targets.find(t => t.type === 'page');
69
+ resolve(page ? page.url : null);
70
+ } catch { resolve(null); }
71
+ });
72
+ });
73
+ req.on('error', () => resolve(null));
74
+ req.on('timeout', () => { req.destroy(); resolve(null); });
75
+ });
76
+ }
77
+
78
+ module.exports = { readStdin, die, probeCDP, findFreePort, sleep, fetchActivePageUrl };