Skip to content

Commit b1d366b

Browse files
committed
fix: resolve global playwright install via createRequire
Dynamic ESM import cannot resolve bare directory paths for globally installed packages. Switch to createRequire which handles node_modules resolution correctly, with fallback to global npm root.
1 parent 16e140a commit b1d366b

1 file changed

Lines changed: 24 additions & 2 deletions

File tree

apps/cli/src/auth/pre-auth.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
* npm install -g playwright && npx playwright install chromium
1111
*/
1212

13+
import { execFileSync } from 'node:child_process';
1314
import fs from 'node:fs';
15+
import { createRequire } from 'node:module';
1416
import path from 'node:path';
1517

1618
export interface PreAuthOptions {
@@ -43,10 +45,30 @@ interface PlaywrightChromium {
4345
launch(opts: { headless: boolean }): Promise<PlaywrightBrowser>;
4446
}
4547

48+
function resolvePlaywrightPath(): string {
49+
// Try local node_modules first, then global
50+
const localPath = path.resolve('node_modules', 'playwright');
51+
if (fs.existsSync(localPath)) return localPath;
52+
53+
try {
54+
const globalRoot = execFileSync('npm', ['root', '-g'], { encoding: 'utf-8' }).trim();
55+
const globalPath = path.join(globalRoot, 'playwright');
56+
if (fs.existsSync(globalPath)) return globalPath;
57+
} catch {
58+
// npm not available or failed
59+
}
60+
61+
return 'playwright'; // Fallback to bare specifier
62+
}
63+
4664
async function loadPlaywright(): Promise<PlaywrightChromium> {
4765
try {
48-
// Dynamic import — playwright is an optional peer dependency, not bundled
49-
const pw = await (Function('return import("playwright")')() as Promise<{ chromium: PlaywrightChromium }>);
66+
// Use createRequire to resolve playwright from local or global node_modules.
67+
// ESM dynamic import can't resolve bare directory paths, but require.resolve can.
68+
const resolved = resolvePlaywrightPath();
69+
const require = createRequire(import.meta.url);
70+
const pw = require(resolved) as { chromium: PlaywrightChromium };
71+
if (!pw.chromium) throw new Error('chromium not found in playwright module');
5072
return pw.chromium;
5173
} catch {
5274
console.error('\nERROR: Playwright is required for interactive authentication.');

0 commit comments

Comments
 (0)