← Public packages
@kody/browser-run
Call Cloudflare Browser Run Quick Actions and reuse shared sessions with createBrowserContext.
src/quick-action.ts
111 lines · 2.9 KB · TypeScriptimport { any, object, optional, parse, string } from 'remix/data-schema'
import {
QUICK_ACTIONS,
accountPath,
browserRunFetch,
isQuickAction,
pickAuth,
requireAccountId,
type AuthOptions,
type QuickActionName,
} from './client.ts'
const quickActionInput = object(
{
accountId: string(),
action: string(),
apiTokenSecret: optional(string()),
/** Request body fields passed through to Cloudflare (url/html/options/…). */
body: optional(any()),
},
{ unknownKeys: 'error' },
)
export type QuickActionInput = AuthOptions & {
action: QuickActionName | string
body?: Record<string, unknown> | unknown
}
/**
* POST a Cloudflare Browser Run Quick Action under
* `/accounts/{accountId}/browser-rendering/{action}`.
* Use for one-shot screenshot, pdf, content, markdown, scrape, links, json,
* snapshot, or accessibilityTree. Binary responses (screenshot/pdf) return
* base64 + contentType.
*
* @param raw.accountId - Cloudflare account id
* @param raw.action - Quick Action name
* @param raw.body - Fields from CF docs (`url` or `html`, viewport, …)
* @param raw.apiTokenSecret - Optional alternate secret **name**
* @returns Structured JSON result or `{ kind: 'binary', base64, contentType }`
*
* @example
* import quickAction from 'kody:@kody/browser-run/quick-action'
* const shot = await quickAction({
* accountId: 'YOUR_ACCOUNT_ID',
* action: 'screenshot',
* body: { url: 'https://example.com' },
* })
*/
export default async function quickAction(raw: unknown = {}) {
const input = parse(quickActionInput, raw ?? {})
const action = String(input.action).trim()
if (!isQuickAction(action)) {
throw new Error(
`Unknown Quick Action "${action}". Valid: ${QUICK_ACTIONS.join(', ')}.`,
)
}
const auth = pickAuth(input)
const accountId = requireAccountId(auth)
const body =
input.body && typeof input.body === 'object' && !Array.isArray(input.body)
? (input.body as Record<string, unknown>)
: {}
const acceptBinary = action === 'screenshot' || action === 'pdf'
const response = await browserRunFetch(
accountPath(accountId, `/browser-rendering/${action}`),
{
...auth,
method: 'POST',
body,
acceptBinary,
},
)
if (response.kind === 'binary') {
return {
ok: true,
action,
accountId,
kind: 'binary' as const,
contentType: response.contentType,
base64: response.base64,
byteLength: response.byteLength,
browserMsUsed: response.browserMsUsed,
}
}
if (response.kind === 'json') {
return {
ok: true,
action,
accountId,
kind: 'json' as const,
result: response.result,
errors: response.errors,
messages: response.messages,
browserMsUsed: response.browserMsUsed,
status: response.status,
}
}
return {
ok: true,
action,
accountId,
kind: 'text' as const,
text: response.text,
contentType: response.contentType,
browserMsUsed: response.browserMsUsed,
status: response.status,
}
}