1- // Browser abstraction layer to support both Puppeteer and Playwright
2- import puppeteer from 'puppeteer' ;
3- import playwright from 'playwright' ;
1+ // Browser abstraction layer using browser-commander for all browser operations
2+ // See: https://github.com/link-foundation/browser-commander
3+
4+ import { launchBrowser } from 'browser-commander' ;
5+ import os from 'os' ;
6+ import path from 'path' ;
7+
8+ /**
9+ * Additional Chrome args needed for headless server environments
10+ * These are appended to browser-commander's default CHROME_ARGS
11+ */
12+ const SERVER_CHROME_ARGS = [
13+ '--no-sandbox' ,
14+ '--disable-setuid-sandbox' ,
15+ '--disable-dev-shm-usage' ,
16+ ] ;
417
518/**
619 * Unified browser interface that works with both Puppeteer and Playwright
@@ -26,78 +39,52 @@ import playwright from 'playwright';
2639
2740/**
2841 * Create a browser instance using the specified engine
42+ * Uses browser-commander's launchBrowser for both Puppeteer and Playwright
2943 * @param {string } engine - 'puppeteer' or 'playwright' (defaults to puppeteer)
3044 * @param {Object } options - Browser launch options
3145 * @returns {Promise<BrowserAdapter> }
3246 */
3347export async function createBrowser ( engine = 'puppeteer' , options = { } ) {
3448 const normalizedEngine = engine . toLowerCase ( ) ;
49+ const engineType =
50+ normalizedEngine === 'playwright' || normalizedEngine === 'pw'
51+ ? 'playwright'
52+ : 'puppeteer' ;
3553
36- if ( normalizedEngine === 'playwright' ) {
37- return createPlaywrightBrowser ( options ) ;
38- } else {
39- return createPuppeteerBrowser ( options ) ;
40- }
41- }
54+ // Generate unique userDataDir for this session to avoid conflicts
55+ const userDataDir = path . join (
56+ os . tmpdir ( ) ,
57+ `web-capture-${ engineType } -${ Date . now ( ) } `
58+ ) ;
4259
43- /**
44- * Create a Puppeteer browser instance
45- * @param {Object } options - Puppeteer launch options
46- * @returns {Promise<BrowserAdapter> }
47- */
48- async function createPuppeteerBrowser ( options = { } ) {
49- const defaultOptions = {
50- args : [
51- '--no-sandbox' ,
52- '--disable-setuid-sandbox' ,
53- '--disable-dev-shm-usage' ,
54- ] ,
55- } ;
56-
57- const browser = await puppeteer . launch ( { ...defaultOptions , ...options } ) ;
58-
59- return {
60- async newPage ( ) {
61- const page = await browser . newPage ( ) ;
62- return createPuppeteerPageAdapter ( page ) ;
63- } ,
64- async close ( ) {
65- await browser . close ( ) ;
66- } ,
67- type : 'puppeteer' ,
68- _browser : browser ,
69- } ;
70- }
71-
72- /**
73- * Create a Playwright browser instance
74- * @param {Object } options - Playwright launch options
75- * @returns {Promise<BrowserAdapter> }
76- */
77- async function createPlaywrightBrowser ( options = { } ) {
78- const defaultOptions = {
79- args : [
80- '--no-sandbox' ,
81- '--disable-setuid-sandbox' ,
82- '--disable-dev-shm-usage' ,
83- ] ,
84- } ;
85-
86- // Playwright uses chromium by default
87- const browser = await playwright . chromium . launch ( {
88- ...defaultOptions ,
60+ // Use browser-commander's launchBrowser with server-specific args
61+ // Default to headless for server environments
62+ const { browser, page } = await launchBrowser ( {
63+ engine : engineType ,
64+ args : SERVER_CHROME_ARGS ,
65+ headless : true ,
66+ userDataDir,
67+ slowMo : 0 , // Disable slowMo for server operations
8968 ...options ,
9069 } ) ;
9170
71+ // Close the initial page since we'll create new ones via newPage()
72+ await page . close ( ) ;
73+
74+ const pageAdapter =
75+ engineType === 'playwright'
76+ ? createPlaywrightPageAdapter
77+ : createPuppeteerPageAdapter ;
78+
9279 return {
9380 async newPage ( ) {
94- const page = await browser . newPage ( ) ;
95- return createPlaywrightPageAdapter ( page ) ;
81+ const newPage = await browser . newPage ( ) ;
82+ return pageAdapter ( newPage ) ;
9683 } ,
9784 async close ( ) {
9885 await browser . close ( ) ;
9986 } ,
100- type : 'playwright' ,
87+ type : engineType ,
10188 _browser : browser ,
10289 } ;
10390}
0 commit comments