@guanzhu.me/pw-cli 0.0.19 → 0.0.21

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": "@guanzhu.me/pw-cli",
3
- "version": "0.0.19",
3
+ "version": "0.0.21",
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"
@@ -11,22 +11,34 @@ const { readState, writeState, clearState, getProfileDir } = require('./state');
11
11
  const { probeCDP, findFreePort, sleep, fetchActivePageUrl } = require('./utils');
12
12
 
13
13
  function loadPlaywrightUtilsBundle() {
14
- const candidates = [
15
- '../node_modules/@playwright/cli/node_modules/playwright-core/lib/utilsBundleImpl',
16
- '../node_modules/@playwright/cli/node_modules/playwright-core/lib/utilsBundleImpl/index.js',
14
+ // playwright-core's package.json "exports" blocks deep subpath requires, so
15
+ // we locate the package root via require.resolve on package.json, then load
16
+ // the internal module by absolute path.
17
+ const searchPaths = [
18
+ path.join(__dirname, '..'), // local dev
19
+ path.join(__dirname, '..', 'node_modules', '@playwright', 'cli'), // nested under pw-cli
17
20
  ];
18
21
 
19
- for (const candidate of candidates) {
22
+ // Also search from the global npm root where @playwright/cli might live
23
+ try {
24
+ const globalRoot = execSync('npm root -g', { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();
25
+ searchPaths.push(path.join(globalRoot, '@playwright', 'cli'));
26
+ searchPaths.push(globalRoot);
27
+ } catch {}
28
+
29
+ for (const searchPath of searchPaths) {
20
30
  try {
21
- return require(candidate);
31
+ const pkgJson = require.resolve('playwright-core/package.json', { paths: [searchPath] });
32
+ const utilsBundle = path.join(path.dirname(pkgJson), 'lib', 'utilsBundleImpl');
33
+ return require(utilsBundle);
22
34
  } catch (error) {
23
- if (error.code !== 'MODULE_NOT_FOUND') {
35
+ if (error.code !== 'MODULE_NOT_FOUND' && error.code !== 'ERR_PACKAGE_PATH_NOT_EXPORTED') {
24
36
  throw error;
25
37
  }
26
38
  }
27
39
  }
28
40
 
29
- throw new Error('Unable to load playwright-core utilsBundleImpl from @playwright/cli. Reinstall @playwright/cli or playwright.');
41
+ throw new Error('Unable to load playwright-core utilsBundleImpl. Reinstall @playwright/cli or playwright.');
30
42
  }
31
43
 
32
44
  const { ws, wsServer } = loadPlaywrightUtilsBundle();
@@ -262,13 +274,14 @@ class ExtensionConnection {
262
274
  }
263
275
 
264
276
  class CDPRelayServer {
265
- constructor(server, browserChannel, userDataDir, executablePath) {
277
+ constructor(server, browserChannel, userDataDir, executablePath, extensionToken) {
266
278
  this._playwrightConnection = null;
267
279
  this._extensionConnection = null;
268
280
  this._nextSessionId = 1;
269
281
  this._browserChannel = browserChannel;
270
282
  this._userDataDir = userDataDir;
271
283
  this._executablePath = executablePath;
284
+ this._extensionToken = extensionToken || null;
272
285
  const uuid = crypto.randomUUID();
273
286
  const address = server.address();
274
287
  this._wsHost = `ws://127.0.0.1:${address.port}`;
@@ -314,6 +327,9 @@ class CDPRelayServer {
314
327
  url.searchParams.set('mcpRelayUrl', relayUrl);
315
328
  url.searchParams.set('client', JSON.stringify({ name: clientName }));
316
329
  url.searchParams.set('protocolVersion', '1');
330
+ if (this._extensionToken) {
331
+ url.searchParams.set('token', this._extensionToken);
332
+ }
317
333
 
318
334
  const executablePath = this._executablePath || resolveExtensionExecutablePath(this._browserChannel);
319
335
  const args = [];
@@ -338,6 +354,13 @@ class CDPRelayServer {
338
354
  return;
339
355
  }
340
356
  if (url.pathname === this._extensionPath) {
357
+ if (this._extensionToken) {
358
+ const token = url.searchParams.get('token');
359
+ if (token !== this._extensionToken) {
360
+ socket.close(4003, 'Invalid token');
361
+ return;
362
+ }
363
+ }
341
364
  this._handleExtensionConnection(socket);
342
365
  return;
343
366
  }
@@ -479,7 +502,8 @@ async function startExtensionRelay(extension) {
479
502
  server.once('error', reject);
480
503
  server.listen(0, '127.0.0.1', resolve);
481
504
  });
482
- const relay = new CDPRelayServer(server, browser, null, null);
505
+ const extensionToken = process.env.PLAYWRIGHT_MCP_EXTENSION_TOKEN || null;
506
+ const relay = new CDPRelayServer(server, browser, null, null, extensionToken);
483
507
  await relay.ensureExtensionConnectionForMCPContext('pw-cli');
484
508
  return { relay, server };
485
509
  }