| import { chromium, Browser, BrowserContext } from 'playwright'; |
| import { config } from '../config'; |
| import { logger } from '../utils/logger'; |
|
|
| let browser: Browser | null = null; |
| let browserLaunchPromise: Promise<Browser> | null = null; |
|
|
| |
| |
| |
| |
| export async function getBrowser(): Promise<Browser> { |
| if (browser && browser.isConnected()) { |
| return browser; |
| } |
|
|
| if (browserLaunchPromise) { |
| return browserLaunchPromise; |
| } |
|
|
| browserLaunchPromise = launchBrowser(); |
|
|
| try { |
| browser = await browserLaunchPromise; |
| return browser; |
| } finally { |
| browserLaunchPromise = null; |
| } |
| } |
|
|
| async function launchBrowser(): Promise<Browser> { |
| logger.info('Launching Chromium browser', { headless: config.headless }); |
|
|
| const b = await chromium.launch({ |
| headless: config.headless, |
| args: [ |
| '--no-sandbox', |
| '--disable-setuid-sandbox', |
| '--disable-dev-shm-usage', |
| '--disable-gpu', |
| ], |
| }); |
|
|
| b.on('disconnected', () => { |
| logger.warn('Browser disconnected'); |
| browser = null; |
| }); |
|
|
| logger.info('Browser launched successfully'); |
| return b; |
| } |
|
|
| |
| |
| |
| |
| export async function createContext( |
| storageState?: string |
| ): Promise<BrowserContext> { |
| const b = await getBrowser(); |
|
|
| const contextOptions: Parameters<Browser['newContext']>[0] = { |
| viewport: { width: 1280, height: 720 }, |
| userAgent: |
| 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36', |
| acceptDownloads: true, |
| }; |
|
|
| if (storageState) { |
| try { |
| contextOptions.storageState = JSON.parse(storageState); |
| } catch { |
| logger.warn('Failed to parse storage state, starting fresh'); |
| } |
| } |
|
|
| const context = await b.newContext(contextOptions); |
|
|
| |
| context.setDefaultTimeout(30000); |
| context.setDefaultNavigationTimeout(60000); |
|
|
| return context; |
| } |
|
|
| |
| |
| |
| export async function closeBrowser(): Promise<void> { |
| if (browser) { |
| try { |
| await browser.close(); |
| } catch { |
| |
| } |
| browser = null; |
| logger.info('Browser closed'); |
| } |
| } |
|
|
| |
| |
| |
| export async function getActiveContextCount(): Promise<number> { |
| if (!browser || !browser.isConnected()) return 0; |
| return browser.contexts().length; |
| } |
|
|