Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
233 changes: 233 additions & 0 deletions packages/playwright-cloudflare/cloudflare-cdp.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
/**
* Type definitions for Cloudflare's custom CDP commands.
*
* Cloudflare's Browser Run platform exposes a non-standard `Cloudflare.*` CDP
* domain that is not part of the upstream DevTools protocol, so it is absent
* from Playwright's generated protocol types. This module declares the request
* and response shapes for those commands and merges them into
* `Protocol.CommandParameters` / `Protocol.CommandReturnValues`, which makes
* calls such as `cdpSession.send('Cloudflare.handoff', {...})` type-check with
* full parameter and return-type inference.
*
* SHARED SOURCE OF TRUTH. The interface block below is intended to be the
* canonical definition of the `Cloudflare.*` CDP types and is vendored
* identically into the puppeteer and playwright forks. When the
* `cloudflare/browser-run` monorepo lands, this block should be promoted to a
* shared package that both ports import, replacing the vendored copies. Keep
* the two copies in sync until then. Only the `declare module` augmentation at
* the bottom is fork-specific.
*
* This file lives outside the build-generated `types/` directory (which is
* overwritten by utils/copy_types.js) so the augmentation survives rebuilds.
*
* @see https://jira.cfdata.org/browse/BRAPI-1194
* @see https://jira.cfdata.org/browse/BRAPI-1218
*/

// ============================================================================
// Shared Cloudflare.* CDP types (canonical — keep in sync across forks)
// ============================================================================

/**
* Live view mode options.
*
* @public
*/
export type LiveViewMode = 'devtools' | 'tab' | 'full';

// ---------------- Cloudflare.handoff ----------------

/**
* @public
*/
export interface HandoffRequest {
/**
* Target page ID requiring intervention.
*/
targetId?: string;
/**
* Human-readable instructions (max 4096 chars).
*/
instructions?: string;
/**
* Timeout in milliseconds (max 30 minutes).
*/
timeout?: number;
}

/**
* @public
*/
export interface HandoffResponse {
/**
* The target page ID.
*/
targetId: string;
/**
* Unique identifier for this handoff.
*/
handoffId: string;
}

// ---------------- Cloudflare.handoffComplete ----------------

/**
* @public
*/
export interface HandoffCompleteRequest {
/**
* Target page ID.
*/
targetId?: string;
/**
* Whether intervention was successful. Defaults to true.
*/
success?: boolean;
/**
* Reason for the result (max 1024 chars).
*/
reason?: string;
}

/**
* @public
*/
export interface HandoffCompleteResponse {
/**
* Target page ID.
*/
targetId: string;
/**
* Unique identifier for the handoff.
*/
handoffId?: string;
/**
* Original instructions for the handoff.
*/
instructions?: string;
/**
* Whether intervention was successful.
*/
success: boolean;
/**
* Reason for the result.
*/
reason?: string;
}

// ---------------- Cloudflare.getHandoffState ----------------

/**
* @public
*/
export interface GetHandoffStateRequest {
/**
* Target page ID.
*/
targetId?: string;
}

/**
* @public
*/
export interface GetHandoffStateResponse {
/**
* Whether a handoff is active.
*/
active: boolean;
/**
* Unique identifier for the handoff.
*/
handoffId?: string;
/**
* Active handoff instructions.
*/
instructions?: string;
/**
* Active handoff timeout in milliseconds.
*/
timeout?: number;
/**
* Elapsed time since handoff started in milliseconds.
*/
durationMs?: number;
}

// ---------------- Cloudflare.getSessionId ----------------

/**
* @public
*/
export type GetSessionIdRequest = Record<string, never>;

/**
* @public
*/
export interface GetSessionIdResponse {
sessionId: string;
}

// ---------------- Cloudflare.getLiveView ----------------

/**
* @public
*/
export interface GetLiveViewRequest {
/**
* Target ID to get live view for. Optional - auto-resolved if omitted.
*/
targetId?: string;
/**
* Live view mode: devtools, tab, or full. Defaults to "devtools".
*/
mode?: LiveViewMode;
}

/**
* @public
*/
export interface GetLiveViewResponse {
/**
* WebSocket URL for the live view.
*/
webSocketDebuggerUrl: string;
/**
* DevTools frontend URL for the live view.
*/
devtoolsFrontendUrl: string;
/**
* The target ID.
*/
id: string;
/**
* Live view options.
*/
options: Record<string, unknown>;
}

// ============================================================================
// Fork-specific augmentation (playwright: merge into the generated Protocol
// CommandParameters / CommandReturnValues maps that CDPSession.send is keyed on)
// ============================================================================

declare module './types/protocol' {
// Augmenting the generated Protocol namespace requires a namespace to match
// its own declaration, so the no-namespace rule does not apply here.
// eslint-disable-next-line @typescript-eslint/no-namespace
export namespace Protocol {
interface CommandParameters {
'Cloudflare.handoff': HandoffRequest;
'Cloudflare.handoffComplete': HandoffCompleteRequest;
'Cloudflare.getHandoffState': GetHandoffStateRequest;
'Cloudflare.getSessionId': GetSessionIdRequest;
'Cloudflare.getLiveView': GetLiveViewRequest;
}
interface CommandReturnValues {
'Cloudflare.handoff': HandoffResponse;
'Cloudflare.handoffComplete': HandoffCompleteResponse;
'Cloudflare.getHandoffState': GetHandoffStateResponse;
'Cloudflare.getSessionId': GetSessionIdResponse;
'Cloudflare.getLiveView': GetLiveViewResponse;
}
}
}
5 changes: 5 additions & 0 deletions packages/playwright-cloudflare/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ import { env } from 'cloudflare:workers';

export * from './types/types';

// Re-export the Cloudflare.* CDP command types and pull in their augmentation
// of Protocol.CommandParameters / CommandReturnValues so that
// cdpSession.send('Cloudflare.*', ...) is typed.
export * from './cloudflare-cdp';

declare module './types/types' {
interface Browser {
/**
Expand Down
Loading