@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 +16 -17
- package/package.json +1 -1
- package/src/utils.js +24 -1
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
|
|
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
|
|
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
|
-
|
|
759
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
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
|
-
|
|
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 };
|