@cityssm/puppeteer-launch
Version:
Launch Puppeteer, falling back to system browsers when the cached ones aren't working or aren't available.
143 lines (115 loc) • 3.75 kB
text/typescript
import Debug from 'debug'
import {
type Browser,
type LaunchOptions,
launch as puppeteerLaunch
} from 'puppeteer'
import { getCachedBrowser } from './cache.js'
import { DEBUG_NAMESPACE } from './debug.config.js'
import { getUserChromePath, getUserFirefoxPath } from './user.js'
const debug = Debug(`${DEBUG_NAMESPACE}:index`)
type RetryBrowser = 'chrome-user' | 'chrome' | 'firefox-user' | 'firefox'
export const browserOrderDefault = [
'chrome',
'firefox',
'chrome-user',
'firefox-user'
] as RetryBrowser[]
/**
* Launches a Puppeteer browser instance.
* Automatically falls back to a system browser if no browser is available in the Puppeteer cache.
* @param options - Optional launch parameters
* @returns - A Puppeteer browser instance.
*/
export default async function launch(
options: LaunchOptions & { browserOrder?: RetryBrowser[] } = {}
): Promise<Browser> {
/*
* Set default Puppeteer options
*/
const puppeteerOptions: LaunchOptions = {
headless: true,
timeout: 60_000,
...options
}
/*
* Set browser order
*/
let browserOrder =
options.browserOrder === undefined ? undefined : [...options.browserOrder]
if (browserOrder === undefined) {
if (puppeteerOptions.browser === 'firefox') {
browserOrder = ['firefox', 'firefox-user']
} else if (puppeteerOptions.browser === 'chrome') {
browserOrder = ['chrome', 'chrome-user']
} else {
browserOrder = browserOrderDefault
}
}
/*
* If no browser is specified, try to load one from the browser order
*/
if (puppeteerOptions.browser === undefined && browserOrder.length > 0) {
const browserToLoad = browserOrder.shift()
debug(`Loading browser: ${browserToLoad}`)
if (browserToLoad === 'firefox-user') {
const firefoxPath = await getUserFirefoxPath()
if (firefoxPath !== undefined) {
puppeteerOptions.executablePath = firefoxPath
}
puppeteerOptions.browser = 'firefox'
} else if (browserToLoad === 'chrome-user') {
const chromePath = await getUserChromePath()
if (chromePath !== undefined) {
puppeteerOptions.executablePath = chromePath
}
puppeteerOptions.browser = 'chrome'
} else {
puppeteerOptions.browser = browserToLoad
const installedBrowser = await getCachedBrowser(
browserToLoad === 'chrome' ? 'chrome' : 'firefox',
true
)
puppeteerOptions.executablePath = installedBrowser?.executablePath
}
}
/*
* Attempt to launch the browser
*/
try {
debug(`Attempting to launch browser: ${JSON.stringify(puppeteerOptions)}`)
const browser = await puppeteerLaunch(puppeteerOptions)
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (browser === undefined) {
throw new Error('Puppeteer browser is undefined')
}
debug('Launched puppeteer browser')
return browser
} catch (error) {
// debug(`Error launching browser: ${error}`)
if (browserOrder.length > 0) {
puppeteerOptions.browser = undefined
puppeteerOptions.executablePath = undefined
return await launch({
...puppeteerOptions,
browserOrder
})
}
throw error
}
}
export {
getCachedBrowser,
getCachedChromeBrowser,
getCachedFirefoxBrowser,
refreshInstalledBrowserCache
} from './cache.js'
export {
installBrowser,
installChromeBrowser,
installFirefoxBrowser,
testInstalledBrowser,
testInstalledChromeBrowser,
testInstalledFirefoxBrowser
} from './installers.js'
export * as puppeteer from 'puppeteer'