@cloudflare/puppeteer
Version:
A high-level API to control headless Chrome over the DevTools Protocol
118 lines • 4.17 kB
JavaScript
/**
* @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.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 searchParams = new URLSearchParams();
if (options?.keep_alive) {
searchParams.set('keep_alive', `${options.keep_alive}`);
}
if (options?.location) {
searchParams.set('location', options.location);
}
const acquireUrl = `${FAKE_HOST}/v1/acquire?${searchParams.toString()}`;
const res = await endpoint.fetch(acquireUrl);
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 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}`);
}
}
}
//# sourceMappingURL=PuppeteerWorkers.js.map