browse
Version:
Unified Browserbase CLI for browser automation and cloud APIs.
95 lines (94 loc) • 3.07 kB
JavaScript
import { stat } from "node:fs/promises";
import { extname, resolve } from "node:path";
import { CommandFailure, fail } from "../errors.js";
import { readBrowserbaseError, resolveApiKey } from "../cloud/api.js";
const defaultFunctionsBaseUrl = "https://api.browserbase.com";
export function resolveFunctionsApiConfig(args) {
return {
apiKey: resolveApiKey(args),
baseUrl: args.baseUrl ||
process.env.BROWSERBASE_BASE_URL ||
process.env.BROWSERBASE_API_BASE_URL ||
defaultFunctionsBaseUrl,
};
}
export async function functionsRequest(config, path, init = {}) {
let response;
try {
response = await fetch(new URL(path, config.baseUrl), {
...init,
headers: {
"x-bb-api-key": config.apiKey,
...(init.headers ?? {}),
},
});
}
catch (error) {
if (error instanceof CommandFailure) {
throw error;
}
fail(error instanceof Error ? error.message : String(error));
}
if (!response.ok) {
fail(await readBrowserbaseError(response));
}
return response;
}
export async function functionsGet(config, path) {
const response = await functionsRequest(config, path);
return (await response.json());
}
export async function functionsPost(config, path, body) {
const response = await functionsRequest(config, path, {
method: "POST",
headers: {
"content-type": "application/json",
},
body: JSON.stringify(body),
});
return (await response.json());
}
export async function pollUntil(loader, options) {
const intervalMs = options.intervalMs ?? 1_000;
const maxAttempts = options.maxAttempts ?? 120;
for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
const result = await loader();
if (options.done(result)) {
return result;
}
await new Promise((resolvePromise) => setTimeout(resolvePromise, intervalMs));
}
fail("Timed out while waiting for the Browserbase Functions operation to complete.");
}
export async function resolveEntrypoint(entrypoint) {
const absolutePath = resolve(entrypoint);
let stats;
try {
stats = await stat(absolutePath);
}
catch {
fail(`Entrypoint file not found: ${absolutePath}`);
}
if (!stats.isFile()) {
fail(`Entrypoint must be a file: ${absolutePath}`);
}
const extension = extname(absolutePath).toLowerCase();
if (![".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".mts"].includes(extension)) {
fail(`Unsupported entrypoint extension: ${extension}`);
}
return absolutePath;
}
export function parseOptionalJsonValueArg(rawValue, label) {
if (!rawValue) {
return {};
}
if (typeof rawValue !== "string") {
fail(`${label} must be provided as a JSON string.`);
}
try {
return JSON.parse(rawValue);
}
catch (error) {
fail(`Invalid JSON for ${label}: ${error.message}`);
}
}