← Public packages
@kody/browser-run
Call Cloudflare Browser Run Quick Actions and reuse shared sessions with createBrowserContext.
src/sessions/close.ts
83 lines · 2.4 KB · TypeScriptimport { boolean, object, optional, parse, string } from 'remix/data-schema'
import {
accountPath,
browserRunFetch,
pickAuth,
requireAccountId,
} from '../client.ts'
const closeInput = object(
{
accountId: string(),
sessionId: string(),
apiTokenSecret: optional(string()),
dryRun: optional(boolean()),
confirm: optional(boolean()),
},
{ unknownKeys: 'error' },
)
/**
* Close a Browser Run session
* (`DELETE .../devtools/browser/{sessionId}`).
* Destructive for every client on that session — requires `confirm: true`
* (or `dryRun: true` to preview). Prefer `context.close()` + `disconnect`
* for shared-session cleanup instead of closing the whole browser.
*
* @param raw.accountId - Cloudflare account id
* @param raw.sessionId - Session to close
* @param raw.confirm - Must be true for the live DELETE
* @param raw.dryRun - Preview without calling CF
* @param raw.apiTokenSecret - Optional alternate secret name
* @returns Close status or dry-run preview
*
* @example
* import closeSession from 'kody:@kody/browser-run/sessions/close'
* const preview = await closeSession({
* accountId: 'YOUR_ACCOUNT_ID',
* sessionId: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e',
* dryRun: true,
* })
*/
export default async function closeSession(raw: unknown = {}) {
const input = parse(closeInput, raw ?? {})
const auth = pickAuth(input)
const accountId = requireAccountId(auth)
const sessionId = String(input.sessionId).trim()
if (!sessionId) throw new Error('sessionId is required.')
const path = accountPath(
accountId,
`/browser-rendering/devtools/browser/${encodeURIComponent(sessionId)}`,
)
if (input.dryRun === true) {
return {
dryRun: true as const,
method: 'DELETE' as const,
path,
accountId,
sessionId,
willCloseSharedBrowser: true,
warning:
'Closing the session terminates the shared browser for every concurrent client. Prefer context.close() + browser.disconnect() when sharing.',
}
}
if (input.confirm !== true) {
throw new Error(
'Refusing to close a Browser Run session without confirm: true. Pass dryRun: true to preview, or confirm: true to DELETE the shared browser.',
)
}
const response = await browserRunFetch(path, { ...auth, method: 'DELETE' })
return {
ok: true,
accountId,
sessionId,
status:
response.kind === 'json'
? (response.result as { status?: string })?.status ?? response.result
: response,
browserMsUsed: response.browserMsUsed,
}
}