UNPKG

@cloudflare/puppeteer

Version:

Puppeteer fork for Cloudflare Browser Run (formerly Browser Rendering)

135 lines 4.74 kB
/** * @license * Copyright 2025 Google Inc. * SPDX-License-Identifier: Apache-2.0 */ import './globalPatcher.js'; import { Puppeteer } from '../common/Puppeteer.js'; import { connectToCDPBrowser } from './utils.js'; import { WorkersWebSocketTransport } from './WorkersWebSocketTransport.js'; const FAKE_HOST = 'https://fake.host'; /** * @public */ export class PuppeteerWorkers extends Puppeteer { constructor() { super({ isPuppeteerCore: false }); this.acquire = this.acquire.bind(this); this.connect = this.connect.bind(this); this.launch = this.launch.bind(this); this.sessions = this.sessions.bind(this); this.history = this.history.bind(this); this.limits = this.limits.bind(this); } /** * Launch a browser session. * * @param endpoint - Cloudflare worker binding * @returns a browser session or throws */ async launch(endpoint, options) { const response = await this.acquire(endpoint, options); return await this.connect(endpoint, response.sessionId); } /** * Returns active sessions * * @remarks * Sessions with a connnectionId already have a worker connection established * * @param endpoint - Cloudflare worker binding * @returns List of active sessions */ async sessions(endpoint) { const res = await endpoint.fetch(`${FAKE_HOST}/v1/sessions`); const status = res.status; const text = await res.text(); if (status !== 200) { throw new Error(`Unable to fetch new sessions: code: ${status}: message: ${text}`); } const data = JSON.parse(text); return data.sessions; } /** * Returns recent sessions (active and closed) * * @param endpoint - Cloudflare worker binding * @returns List of recent sessions (active and closed) */ async history(endpoint) { const res = await endpoint.fetch(`${FAKE_HOST}/v1/history`); const status = res.status; const text = await res.text(); if (status !== 200) { throw new Error(`Unable to fetch account history: code: ${status}: message: ${text}`); } const data = JSON.parse(text); return data.history; } /** * Returns current limits * * @param endpoint - Cloudflare worker binding * @returns current limits */ async limits(endpoint) { const res = await endpoint.fetch(`${FAKE_HOST}/v1/limits`); const status = res.status; const text = await res.text(); if (status !== 200) { throw new Error(`Unable to fetch account limits: code: ${status}: message: ${text}`); } const data = JSON.parse(text); return data; } /** * Establish a devtools connection to an existing session * * @param borwserWorker - BrowserWorker * @returns a browser instance */ async connect(endpoint, sessionId) { try { if (!sessionId) { return await super.connect(endpoint); } const connectionTransport = await WorkersWebSocketTransport.create(endpoint, sessionId); return await connectToCDPBrowser(connectionTransport, { sessionId }); } catch (e) { throw new Error(`Unable to connect to existing session ${sessionId} (it may still be in use or not ready yet) - retry or launch a new browser: ${e}`); } } /** * Acquire a new browser session. * * @param borwserWorker - BrowserWorker * @returns a new browser session */ async acquire(endpoint, options) { const searchParams = new URLSearchParams(); if (options?.keep_alive) { searchParams.set('keep_alive', `${options.keep_alive}`); } if (options?.location) { searchParams.set('location', options.location); } if (options?.recording) { searchParams.set('recording', options.recording.toString()); } if (options?.lab) { searchParams.set('lab', options.lab.toString()); } const acquireUrl = `${FAKE_HOST}/v1/devtools/browser?${searchParams.toString()}`; const res = await endpoint.fetch(acquireUrl, { method: 'POST' }); const status = res.status; const text = await res.text(); if (status !== 200) { throw new Error(`Unable to create new browser: code: ${status}: message: ${text}`); } // Got a 200, so response text is actually an AcquireResponse const response = JSON.parse(text); return response; } } //# sourceMappingURL=PuppeteerWorkers.js.map