@computesdk/browserbase 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/index.cjs +246 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +37 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.js +211 -0
- package/dist/index.js.map +1 -0
- package/package.json +68 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 computesdk
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
browserbase: () => browserbase
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(index_exports);
|
|
36
|
+
var import_sdk = __toESM(require("@browserbasehq/sdk"), 1);
|
|
37
|
+
var import_provider = require("@computesdk/provider");
|
|
38
|
+
function resolveConfig(config) {
|
|
39
|
+
const apiKey = config.apiKey || typeof process !== "undefined" && process.env?.BROWSERBASE_API_KEY || "";
|
|
40
|
+
const projectId = config.projectId || typeof process !== "undefined" && process.env?.BROWSERBASE_PROJECT_ID || "";
|
|
41
|
+
if (!apiKey) {
|
|
42
|
+
throw new Error(
|
|
43
|
+
`Missing Browserbase API key. Provide 'apiKey' in config or set BROWSERBASE_API_KEY environment variable. Get your API key from https://www.browserbase.com/settings`
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
return { apiKey, projectId };
|
|
47
|
+
}
|
|
48
|
+
function createClient(config) {
|
|
49
|
+
const { apiKey } = resolveConfig(config);
|
|
50
|
+
return new import_sdk.default({ apiKey });
|
|
51
|
+
}
|
|
52
|
+
function mapSessionOptions(config, options) {
|
|
53
|
+
const { projectId } = resolveConfig(config);
|
|
54
|
+
if (!options) {
|
|
55
|
+
return projectId ? { projectId } : {};
|
|
56
|
+
}
|
|
57
|
+
const params = {};
|
|
58
|
+
if (projectId) params.projectId = projectId;
|
|
59
|
+
if (options.region) params.region = options.region;
|
|
60
|
+
if (options.keepAlive !== void 0) params.keepAlive = options.keepAlive;
|
|
61
|
+
if (options.timeout !== void 0) params.timeout = options.timeout;
|
|
62
|
+
if (options.extensionIds?.[0]) params.extensionId = options.extensionIds[0];
|
|
63
|
+
if (options.userMetadata) params.userMetadata = options.userMetadata;
|
|
64
|
+
if (options.proxies === true) {
|
|
65
|
+
params.proxies = true;
|
|
66
|
+
} else if (Array.isArray(options.proxies)) {
|
|
67
|
+
params.proxies = options.proxies.map((p) => {
|
|
68
|
+
if (p.type === "custom" && p.server) {
|
|
69
|
+
return {
|
|
70
|
+
type: "external",
|
|
71
|
+
server: p.server,
|
|
72
|
+
username: p.username,
|
|
73
|
+
password: p.password,
|
|
74
|
+
domainPattern: p.domainPattern
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
type: "browserbase",
|
|
79
|
+
geolocation: p.geolocation,
|
|
80
|
+
domainPattern: p.domainPattern
|
|
81
|
+
};
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
const browserSettings = {};
|
|
85
|
+
if (options.viewport) browserSettings.viewport = options.viewport;
|
|
86
|
+
if (options.stealth !== void 0) browserSettings.advancedStealth = options.stealth;
|
|
87
|
+
if (options.recording !== void 0) browserSettings.recordSession = options.recording;
|
|
88
|
+
if (options.logging !== void 0) browserSettings.logSession = options.logging;
|
|
89
|
+
if (options.profileId) {
|
|
90
|
+
browserSettings.context = { id: options.profileId, persist: true };
|
|
91
|
+
}
|
|
92
|
+
if (Object.keys(browserSettings).length > 0) {
|
|
93
|
+
params.browserSettings = browserSettings;
|
|
94
|
+
}
|
|
95
|
+
return params;
|
|
96
|
+
}
|
|
97
|
+
function normalizeSession(session) {
|
|
98
|
+
return {
|
|
99
|
+
session,
|
|
100
|
+
sessionId: session.id,
|
|
101
|
+
connectUrl: session.connectUrl,
|
|
102
|
+
status: mapStatus(session.status)
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
function mapStatus(status) {
|
|
106
|
+
switch (status) {
|
|
107
|
+
case "RUNNING":
|
|
108
|
+
return "running";
|
|
109
|
+
case "COMPLETED":
|
|
110
|
+
return "completed";
|
|
111
|
+
case "FAILED":
|
|
112
|
+
case "ERROR":
|
|
113
|
+
return "failed";
|
|
114
|
+
case "TIMED_OUT":
|
|
115
|
+
return "timed_out";
|
|
116
|
+
default:
|
|
117
|
+
return "created";
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
var browserbase = (0, import_provider.defineBrowserProvider)({
|
|
121
|
+
name: "browserbase",
|
|
122
|
+
methods: {
|
|
123
|
+
// ─── Session Lifecycle ─────────────────────────────────────────────
|
|
124
|
+
session: {
|
|
125
|
+
create: async (config, options) => {
|
|
126
|
+
const client = createClient(config);
|
|
127
|
+
const params = mapSessionOptions(config, options);
|
|
128
|
+
const session = await client.sessions.create(params);
|
|
129
|
+
return normalizeSession(session);
|
|
130
|
+
},
|
|
131
|
+
getById: async (config, sessionId) => {
|
|
132
|
+
const client = createClient(config);
|
|
133
|
+
try {
|
|
134
|
+
const session = await client.sessions.retrieve(sessionId);
|
|
135
|
+
return normalizeSession(session);
|
|
136
|
+
} catch {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
list: async (config) => {
|
|
141
|
+
const client = createClient(config);
|
|
142
|
+
const response = await client.sessions.list();
|
|
143
|
+
return response.map(normalizeSession);
|
|
144
|
+
},
|
|
145
|
+
destroy: async (config, sessionId) => {
|
|
146
|
+
const client = createClient(config);
|
|
147
|
+
await client.sessions.update(sessionId, { status: "REQUEST_RELEASE" });
|
|
148
|
+
},
|
|
149
|
+
getConnectUrl: async (config, sessionId) => {
|
|
150
|
+
const client = createClient(config);
|
|
151
|
+
const session = await client.sessions.retrieve(sessionId);
|
|
152
|
+
return session.connectUrl;
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
// ─── Profiles (Browserbase Contexts) ───────────────────────────────
|
|
156
|
+
profile: {
|
|
157
|
+
create: async (config, options) => {
|
|
158
|
+
const client = createClient(config);
|
|
159
|
+
const { projectId } = resolveConfig(config);
|
|
160
|
+
const result = await client.contexts.create(projectId ? { projectId } : {});
|
|
161
|
+
return {
|
|
162
|
+
profileId: result.id,
|
|
163
|
+
name: options?.name,
|
|
164
|
+
metadata: options?.metadata
|
|
165
|
+
};
|
|
166
|
+
},
|
|
167
|
+
get: async (config, profileId) => {
|
|
168
|
+
const client = createClient(config);
|
|
169
|
+
try {
|
|
170
|
+
const result = await client.contexts.retrieve(profileId);
|
|
171
|
+
return { profileId: result.id };
|
|
172
|
+
} catch {
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
list: async (_config) => {
|
|
177
|
+
return [];
|
|
178
|
+
},
|
|
179
|
+
delete: async (config, profileId) => {
|
|
180
|
+
const client = createClient(config);
|
|
181
|
+
await client.contexts.delete(profileId);
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
// ─── Extensions ────────────────────────────────────────────────────
|
|
185
|
+
extension: {
|
|
186
|
+
create: async (config, options) => {
|
|
187
|
+
const client = createClient(config);
|
|
188
|
+
const blob = typeof options.file === "string" ? new Blob([options.file]) : new Blob([new Uint8Array(options.file).buffer]);
|
|
189
|
+
const file = new File([blob], options.name ?? "extension.zip");
|
|
190
|
+
const result = await client.extensions.create({ file });
|
|
191
|
+
return {
|
|
192
|
+
extensionId: result.id,
|
|
193
|
+
name: options.name
|
|
194
|
+
};
|
|
195
|
+
},
|
|
196
|
+
get: async (config, extensionId) => {
|
|
197
|
+
const client = createClient(config);
|
|
198
|
+
try {
|
|
199
|
+
const result = await client.extensions.retrieve(extensionId);
|
|
200
|
+
return { extensionId: result.id };
|
|
201
|
+
} catch {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
},
|
|
205
|
+
delete: async (config, extensionId) => {
|
|
206
|
+
const client = createClient(config);
|
|
207
|
+
await client.extensions.delete(extensionId);
|
|
208
|
+
}
|
|
209
|
+
},
|
|
210
|
+
// ─── Logs ──────────────────────────────────────────────────────────
|
|
211
|
+
logs: {
|
|
212
|
+
list: async (config, sessionId) => {
|
|
213
|
+
const client = createClient(config);
|
|
214
|
+
const response = await client.sessions.logs.list(sessionId);
|
|
215
|
+
return response.map((log) => ({
|
|
216
|
+
timestamp: new Date(log.timestamp),
|
|
217
|
+
level: log.level ?? "info",
|
|
218
|
+
message: log.message ?? "",
|
|
219
|
+
data: log.params
|
|
220
|
+
}));
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
// ─── Recordings ────────────────────────────────────────────────────
|
|
224
|
+
recording: {
|
|
225
|
+
get: async (config, sessionId) => {
|
|
226
|
+
const client = createClient(config);
|
|
227
|
+
try {
|
|
228
|
+
const data = await client.sessions.recording.retrieve(sessionId);
|
|
229
|
+
return {
|
|
230
|
+
recordingId: sessionId,
|
|
231
|
+
sessionId,
|
|
232
|
+
format: "rrweb",
|
|
233
|
+
data
|
|
234
|
+
};
|
|
235
|
+
} catch {
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
243
|
+
0 && (module.exports = {
|
|
244
|
+
browserbase
|
|
245
|
+
});
|
|
246
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Browserbase Browser Provider - Factory-based Implementation\n *\n * Cloud browser sessions with stealth mode, proxies, session replay,\n * and persistent contexts via the Browserbase platform.\n */\n\nimport Browserbase from '@browserbasehq/sdk';\nimport { defineBrowserProvider } from '@computesdk/provider';\n\nimport type {\n CreateBrowserSessionOptions,\n BrowserProfile,\n BrowserExtension,\n BrowserLog,\n BrowserRecording,\n} from '@computesdk/provider';\n\n/**\n * Browserbase-specific configuration options\n */\nexport interface BrowserbaseConfig {\n /** Browserbase API key — falls back to BROWSERBASE_API_KEY env var */\n apiKey?: string;\n /** Browserbase project ID — falls back to BROWSERBASE_PROJECT_ID env var */\n projectId?: string;\n}\n\n/**\n * The native Browserbase session object returned by their SDK\n */\ntype BrowserbaseSession = Awaited<ReturnType<InstanceType<typeof Browserbase>['sessions']['create']>>;\n\n/**\n * Resolve config values from explicit config or environment variables\n */\nfunction resolveConfig(config: BrowserbaseConfig) {\n const apiKey = config.apiKey || (typeof process !== 'undefined' && process.env?.BROWSERBASE_API_KEY) || '';\n const projectId = config.projectId || (typeof process !== 'undefined' && process.env?.BROWSERBASE_PROJECT_ID) || '';\n\n if (!apiKey) {\n throw new Error(\n `Missing Browserbase API key. Provide 'apiKey' in config or set BROWSERBASE_API_KEY environment variable. ` +\n `Get your API key from https://www.browserbase.com/settings`\n );\n }\n\n return { apiKey, projectId };\n}\n\n/**\n * Create a Browserbase SDK client from config\n */\nfunction createClient(config: BrowserbaseConfig): Browserbase {\n const { apiKey } = resolveConfig(config);\n return new Browserbase({ apiKey });\n}\n\n/**\n * Map ComputeSDK session options to Browserbase create session params\n */\nfunction mapSessionOptions(config: BrowserbaseConfig, options?: CreateBrowserSessionOptions) {\n const { projectId } = resolveConfig(config);\n\n if (!options) {\n return projectId ? { projectId } : {};\n }\n\n const params: Record<string, any> = {};\n if (projectId) params.projectId = projectId;\n if (options.region) params.region = options.region;\n if (options.keepAlive !== undefined) params.keepAlive = options.keepAlive;\n if (options.timeout !== undefined) params.timeout = options.timeout;\n // Browserbase accepts a single extensionId per session\n if (options.extensionIds?.[0]) params.extensionId = options.extensionIds[0];\n if (options.userMetadata) params.userMetadata = options.userMetadata;\n\n // Proxy configuration\n if (options.proxies === true) {\n params.proxies = true;\n } else if (Array.isArray(options.proxies)) {\n params.proxies = options.proxies.map((p: any) => {\n if (p.type === 'custom' && p.server) {\n return {\n type: 'external' as const,\n server: p.server,\n username: p.username,\n password: p.password,\n domainPattern: p.domainPattern,\n };\n }\n return {\n type: 'browserbase' as const,\n geolocation: p.geolocation,\n domainPattern: p.domainPattern,\n };\n });\n }\n\n // Browser settings\n const browserSettings: Record<string, any> = {};\n if (options.viewport) browserSettings.viewport = options.viewport;\n if (options.stealth !== undefined) browserSettings.advancedStealth = options.stealth;\n if (options.recording !== undefined) browserSettings.recordSession = options.recording;\n if (options.logging !== undefined) browserSettings.logSession = options.logging;\n if (options.profileId) {\n browserSettings.context = { id: options.profileId, persist: true };\n }\n\n if (Object.keys(browserSettings).length > 0) {\n params.browserSettings = browserSettings;\n }\n\n return params;\n}\n\n/**\n * Normalize a Browserbase session into our standard shape\n */\nfunction normalizeSession(session: BrowserbaseSession) {\n return {\n session,\n sessionId: session.id,\n connectUrl: session.connectUrl,\n status: mapStatus(session.status),\n };\n}\n\nfunction mapStatus(status: string): 'created' | 'running' | 'completed' | 'failed' | 'timed_out' {\n switch (status) {\n case 'RUNNING': return 'running';\n case 'COMPLETED': return 'completed';\n case 'FAILED':\n case 'ERROR': return 'failed';\n case 'TIMED_OUT': return 'timed_out';\n default: return 'created';\n }\n}\n\n/**\n * Create a Browserbase browser provider instance\n *\n * @example\n * ```ts\n * import { browserbase } from '@computesdk/browserbase';\n *\n * const bb = browserbase({ apiKey: 'bb_live_...' });\n *\n * // Create a stealth browser session\n * const session = await bb.session.create({ stealth: true, proxies: true });\n * console.log(session.connectUrl);\n *\n * // Connect with Playwright\n * const browser = await chromium.connectOverCDP(session.connectUrl);\n * const page = browser.contexts()[0].pages()[0];\n * await page.goto('https://example.com');\n *\n * // Get session recording after\n * const recording = await session.getRecording();\n * ```\n */\nexport const browserbase = defineBrowserProvider<BrowserbaseSession, BrowserbaseConfig>({\n name: 'browserbase',\n methods: {\n // ─── Session Lifecycle ─────────────────────────────────────────────\n session: {\n create: async (config, options) => {\n const client = createClient(config);\n const params = mapSessionOptions(config, options);\n const session = await client.sessions.create(params);\n return normalizeSession(session);\n },\n\n getById: async (config, sessionId) => {\n const client = createClient(config);\n try {\n const session = await client.sessions.retrieve(sessionId);\n return normalizeSession(session as BrowserbaseSession);\n } catch {\n return null;\n }\n },\n\n list: async (config) => {\n const client = createClient(config);\n const response = await client.sessions.list();\n return (response as BrowserbaseSession[]).map(normalizeSession);\n },\n\n destroy: async (config, sessionId) => {\n const client = createClient(config);\n await client.sessions.update(sessionId, { status: 'REQUEST_RELEASE' });\n },\n\n getConnectUrl: async (config, sessionId) => {\n const client = createClient(config);\n const session = await client.sessions.retrieve(sessionId);\n return (session as BrowserbaseSession).connectUrl;\n },\n },\n\n // ─── Profiles (Browserbase Contexts) ───────────────────────────────\n profile: {\n create: async (config, options) => {\n const client = createClient(config);\n const { projectId } = resolveConfig(config);\n const result = await client.contexts.create(projectId ? { projectId } : {});\n return {\n profileId: result.id,\n name: options?.name,\n metadata: options?.metadata as Record<string, unknown> | undefined,\n } satisfies BrowserProfile;\n },\n\n get: async (config, profileId) => {\n const client = createClient(config);\n try {\n const result = await client.contexts.retrieve(profileId);\n return { profileId: result.id } satisfies BrowserProfile;\n } catch {\n return null;\n }\n },\n\n list: async (_config) => {\n // Browserbase API doesn't expose a list contexts endpoint\n // Return empty — users track their own context IDs\n return [];\n },\n\n delete: async (config, profileId) => {\n const client = createClient(config);\n await client.contexts.delete(profileId);\n },\n },\n\n // ─── Extensions ────────────────────────────────────────────────────\n extension: {\n create: async (config, options) => {\n const client = createClient(config);\n const blob = typeof options.file === 'string'\n ? new Blob([options.file])\n : new Blob([new Uint8Array(options.file).buffer as ArrayBuffer]);\n const file = new File([blob], options.name ?? 'extension.zip');\n const result = await client.extensions.create({ file });\n return {\n extensionId: result.id,\n name: options.name,\n } satisfies BrowserExtension;\n },\n\n get: async (config, extensionId) => {\n const client = createClient(config);\n try {\n const result = await client.extensions.retrieve(extensionId);\n return { extensionId: result.id } satisfies BrowserExtension;\n } catch {\n return null;\n }\n },\n\n delete: async (config, extensionId) => {\n const client = createClient(config);\n await client.extensions.delete(extensionId);\n },\n },\n\n // ─── Logs ──────────────────────────────────────────────────────────\n logs: {\n list: async (config, sessionId) => {\n const client = createClient(config);\n const response = await client.sessions.logs.list(sessionId);\n return (response as any[]).map(log => ({\n timestamp: new Date(log.timestamp),\n level: (log.level ?? 'info') as BrowserLog['level'],\n message: log.message ?? '',\n data: log.params,\n }));\n },\n },\n\n // ─── Recordings ────────────────────────────────────────────────────\n recording: {\n get: async (config, sessionId) => {\n const client = createClient(config);\n try {\n const data = await client.sessions.recording.retrieve(sessionId);\n return {\n recordingId: sessionId,\n sessionId,\n format: 'rrweb',\n data,\n } satisfies BrowserRecording;\n } catch {\n return null;\n }\n },\n },\n },\n});\n"],"mappings":"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","names":["Browserbase"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import * as _computesdk_provider from '@computesdk/provider';
|
|
2
|
+
import Browserbase from '@browserbasehq/sdk';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Browserbase-specific configuration options
|
|
6
|
+
*/
|
|
7
|
+
interface BrowserbaseConfig {
|
|
8
|
+
/** Browserbase API key — falls back to BROWSERBASE_API_KEY env var */
|
|
9
|
+
apiKey?: string;
|
|
10
|
+
/** Browserbase project ID — falls back to BROWSERBASE_PROJECT_ID env var */
|
|
11
|
+
projectId?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Create a Browserbase browser provider instance
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* import { browserbase } from '@computesdk/browserbase';
|
|
19
|
+
*
|
|
20
|
+
* const bb = browserbase({ apiKey: 'bb_live_...' });
|
|
21
|
+
*
|
|
22
|
+
* // Create a stealth browser session
|
|
23
|
+
* const session = await bb.session.create({ stealth: true, proxies: true });
|
|
24
|
+
* console.log(session.connectUrl);
|
|
25
|
+
*
|
|
26
|
+
* // Connect with Playwright
|
|
27
|
+
* const browser = await chromium.connectOverCDP(session.connectUrl);
|
|
28
|
+
* const page = browser.contexts()[0].pages()[0];
|
|
29
|
+
* await page.goto('https://example.com');
|
|
30
|
+
*
|
|
31
|
+
* // Get session recording after
|
|
32
|
+
* const recording = await session.getRecording();
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
declare const browserbase: (config: BrowserbaseConfig) => _computesdk_provider.BrowserProvider<Browserbase.Sessions.SessionCreateResponse>;
|
|
36
|
+
|
|
37
|
+
export { type BrowserbaseConfig, browserbase };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import * as _computesdk_provider from '@computesdk/provider';
|
|
2
|
+
import Browserbase from '@browserbasehq/sdk';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Browserbase-specific configuration options
|
|
6
|
+
*/
|
|
7
|
+
interface BrowserbaseConfig {
|
|
8
|
+
/** Browserbase API key — falls back to BROWSERBASE_API_KEY env var */
|
|
9
|
+
apiKey?: string;
|
|
10
|
+
/** Browserbase project ID — falls back to BROWSERBASE_PROJECT_ID env var */
|
|
11
|
+
projectId?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Create a Browserbase browser provider instance
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* import { browserbase } from '@computesdk/browserbase';
|
|
19
|
+
*
|
|
20
|
+
* const bb = browserbase({ apiKey: 'bb_live_...' });
|
|
21
|
+
*
|
|
22
|
+
* // Create a stealth browser session
|
|
23
|
+
* const session = await bb.session.create({ stealth: true, proxies: true });
|
|
24
|
+
* console.log(session.connectUrl);
|
|
25
|
+
*
|
|
26
|
+
* // Connect with Playwright
|
|
27
|
+
* const browser = await chromium.connectOverCDP(session.connectUrl);
|
|
28
|
+
* const page = browser.contexts()[0].pages()[0];
|
|
29
|
+
* await page.goto('https://example.com');
|
|
30
|
+
*
|
|
31
|
+
* // Get session recording after
|
|
32
|
+
* const recording = await session.getRecording();
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
declare const browserbase: (config: BrowserbaseConfig) => _computesdk_provider.BrowserProvider<Browserbase.Sessions.SessionCreateResponse>;
|
|
36
|
+
|
|
37
|
+
export { type BrowserbaseConfig, browserbase };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import Browserbase from "@browserbasehq/sdk";
|
|
3
|
+
import { defineBrowserProvider } from "@computesdk/provider";
|
|
4
|
+
function resolveConfig(config) {
|
|
5
|
+
const apiKey = config.apiKey || typeof process !== "undefined" && process.env?.BROWSERBASE_API_KEY || "";
|
|
6
|
+
const projectId = config.projectId || typeof process !== "undefined" && process.env?.BROWSERBASE_PROJECT_ID || "";
|
|
7
|
+
if (!apiKey) {
|
|
8
|
+
throw new Error(
|
|
9
|
+
`Missing Browserbase API key. Provide 'apiKey' in config or set BROWSERBASE_API_KEY environment variable. Get your API key from https://www.browserbase.com/settings`
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
return { apiKey, projectId };
|
|
13
|
+
}
|
|
14
|
+
function createClient(config) {
|
|
15
|
+
const { apiKey } = resolveConfig(config);
|
|
16
|
+
return new Browserbase({ apiKey });
|
|
17
|
+
}
|
|
18
|
+
function mapSessionOptions(config, options) {
|
|
19
|
+
const { projectId } = resolveConfig(config);
|
|
20
|
+
if (!options) {
|
|
21
|
+
return projectId ? { projectId } : {};
|
|
22
|
+
}
|
|
23
|
+
const params = {};
|
|
24
|
+
if (projectId) params.projectId = projectId;
|
|
25
|
+
if (options.region) params.region = options.region;
|
|
26
|
+
if (options.keepAlive !== void 0) params.keepAlive = options.keepAlive;
|
|
27
|
+
if (options.timeout !== void 0) params.timeout = options.timeout;
|
|
28
|
+
if (options.extensionIds?.[0]) params.extensionId = options.extensionIds[0];
|
|
29
|
+
if (options.userMetadata) params.userMetadata = options.userMetadata;
|
|
30
|
+
if (options.proxies === true) {
|
|
31
|
+
params.proxies = true;
|
|
32
|
+
} else if (Array.isArray(options.proxies)) {
|
|
33
|
+
params.proxies = options.proxies.map((p) => {
|
|
34
|
+
if (p.type === "custom" && p.server) {
|
|
35
|
+
return {
|
|
36
|
+
type: "external",
|
|
37
|
+
server: p.server,
|
|
38
|
+
username: p.username,
|
|
39
|
+
password: p.password,
|
|
40
|
+
domainPattern: p.domainPattern
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
type: "browserbase",
|
|
45
|
+
geolocation: p.geolocation,
|
|
46
|
+
domainPattern: p.domainPattern
|
|
47
|
+
};
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
const browserSettings = {};
|
|
51
|
+
if (options.viewport) browserSettings.viewport = options.viewport;
|
|
52
|
+
if (options.stealth !== void 0) browserSettings.advancedStealth = options.stealth;
|
|
53
|
+
if (options.recording !== void 0) browserSettings.recordSession = options.recording;
|
|
54
|
+
if (options.logging !== void 0) browserSettings.logSession = options.logging;
|
|
55
|
+
if (options.profileId) {
|
|
56
|
+
browserSettings.context = { id: options.profileId, persist: true };
|
|
57
|
+
}
|
|
58
|
+
if (Object.keys(browserSettings).length > 0) {
|
|
59
|
+
params.browserSettings = browserSettings;
|
|
60
|
+
}
|
|
61
|
+
return params;
|
|
62
|
+
}
|
|
63
|
+
function normalizeSession(session) {
|
|
64
|
+
return {
|
|
65
|
+
session,
|
|
66
|
+
sessionId: session.id,
|
|
67
|
+
connectUrl: session.connectUrl,
|
|
68
|
+
status: mapStatus(session.status)
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function mapStatus(status) {
|
|
72
|
+
switch (status) {
|
|
73
|
+
case "RUNNING":
|
|
74
|
+
return "running";
|
|
75
|
+
case "COMPLETED":
|
|
76
|
+
return "completed";
|
|
77
|
+
case "FAILED":
|
|
78
|
+
case "ERROR":
|
|
79
|
+
return "failed";
|
|
80
|
+
case "TIMED_OUT":
|
|
81
|
+
return "timed_out";
|
|
82
|
+
default:
|
|
83
|
+
return "created";
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
var browserbase = defineBrowserProvider({
|
|
87
|
+
name: "browserbase",
|
|
88
|
+
methods: {
|
|
89
|
+
// ─── Session Lifecycle ─────────────────────────────────────────────
|
|
90
|
+
session: {
|
|
91
|
+
create: async (config, options) => {
|
|
92
|
+
const client = createClient(config);
|
|
93
|
+
const params = mapSessionOptions(config, options);
|
|
94
|
+
const session = await client.sessions.create(params);
|
|
95
|
+
return normalizeSession(session);
|
|
96
|
+
},
|
|
97
|
+
getById: async (config, sessionId) => {
|
|
98
|
+
const client = createClient(config);
|
|
99
|
+
try {
|
|
100
|
+
const session = await client.sessions.retrieve(sessionId);
|
|
101
|
+
return normalizeSession(session);
|
|
102
|
+
} catch {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
list: async (config) => {
|
|
107
|
+
const client = createClient(config);
|
|
108
|
+
const response = await client.sessions.list();
|
|
109
|
+
return response.map(normalizeSession);
|
|
110
|
+
},
|
|
111
|
+
destroy: async (config, sessionId) => {
|
|
112
|
+
const client = createClient(config);
|
|
113
|
+
await client.sessions.update(sessionId, { status: "REQUEST_RELEASE" });
|
|
114
|
+
},
|
|
115
|
+
getConnectUrl: async (config, sessionId) => {
|
|
116
|
+
const client = createClient(config);
|
|
117
|
+
const session = await client.sessions.retrieve(sessionId);
|
|
118
|
+
return session.connectUrl;
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
// ─── Profiles (Browserbase Contexts) ───────────────────────────────
|
|
122
|
+
profile: {
|
|
123
|
+
create: async (config, options) => {
|
|
124
|
+
const client = createClient(config);
|
|
125
|
+
const { projectId } = resolveConfig(config);
|
|
126
|
+
const result = await client.contexts.create(projectId ? { projectId } : {});
|
|
127
|
+
return {
|
|
128
|
+
profileId: result.id,
|
|
129
|
+
name: options?.name,
|
|
130
|
+
metadata: options?.metadata
|
|
131
|
+
};
|
|
132
|
+
},
|
|
133
|
+
get: async (config, profileId) => {
|
|
134
|
+
const client = createClient(config);
|
|
135
|
+
try {
|
|
136
|
+
const result = await client.contexts.retrieve(profileId);
|
|
137
|
+
return { profileId: result.id };
|
|
138
|
+
} catch {
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
list: async (_config) => {
|
|
143
|
+
return [];
|
|
144
|
+
},
|
|
145
|
+
delete: async (config, profileId) => {
|
|
146
|
+
const client = createClient(config);
|
|
147
|
+
await client.contexts.delete(profileId);
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
// ─── Extensions ────────────────────────────────────────────────────
|
|
151
|
+
extension: {
|
|
152
|
+
create: async (config, options) => {
|
|
153
|
+
const client = createClient(config);
|
|
154
|
+
const blob = typeof options.file === "string" ? new Blob([options.file]) : new Blob([new Uint8Array(options.file).buffer]);
|
|
155
|
+
const file = new File([blob], options.name ?? "extension.zip");
|
|
156
|
+
const result = await client.extensions.create({ file });
|
|
157
|
+
return {
|
|
158
|
+
extensionId: result.id,
|
|
159
|
+
name: options.name
|
|
160
|
+
};
|
|
161
|
+
},
|
|
162
|
+
get: async (config, extensionId) => {
|
|
163
|
+
const client = createClient(config);
|
|
164
|
+
try {
|
|
165
|
+
const result = await client.extensions.retrieve(extensionId);
|
|
166
|
+
return { extensionId: result.id };
|
|
167
|
+
} catch {
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
delete: async (config, extensionId) => {
|
|
172
|
+
const client = createClient(config);
|
|
173
|
+
await client.extensions.delete(extensionId);
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
// ─── Logs ──────────────────────────────────────────────────────────
|
|
177
|
+
logs: {
|
|
178
|
+
list: async (config, sessionId) => {
|
|
179
|
+
const client = createClient(config);
|
|
180
|
+
const response = await client.sessions.logs.list(sessionId);
|
|
181
|
+
return response.map((log) => ({
|
|
182
|
+
timestamp: new Date(log.timestamp),
|
|
183
|
+
level: log.level ?? "info",
|
|
184
|
+
message: log.message ?? "",
|
|
185
|
+
data: log.params
|
|
186
|
+
}));
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
// ─── Recordings ────────────────────────────────────────────────────
|
|
190
|
+
recording: {
|
|
191
|
+
get: async (config, sessionId) => {
|
|
192
|
+
const client = createClient(config);
|
|
193
|
+
try {
|
|
194
|
+
const data = await client.sessions.recording.retrieve(sessionId);
|
|
195
|
+
return {
|
|
196
|
+
recordingId: sessionId,
|
|
197
|
+
sessionId,
|
|
198
|
+
format: "rrweb",
|
|
199
|
+
data
|
|
200
|
+
};
|
|
201
|
+
} catch {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
export {
|
|
209
|
+
browserbase
|
|
210
|
+
};
|
|
211
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Browserbase Browser Provider - Factory-based Implementation\n *\n * Cloud browser sessions with stealth mode, proxies, session replay,\n * and persistent contexts via the Browserbase platform.\n */\n\nimport Browserbase from '@browserbasehq/sdk';\nimport { defineBrowserProvider } from '@computesdk/provider';\n\nimport type {\n CreateBrowserSessionOptions,\n BrowserProfile,\n BrowserExtension,\n BrowserLog,\n BrowserRecording,\n} from '@computesdk/provider';\n\n/**\n * Browserbase-specific configuration options\n */\nexport interface BrowserbaseConfig {\n /** Browserbase API key — falls back to BROWSERBASE_API_KEY env var */\n apiKey?: string;\n /** Browserbase project ID — falls back to BROWSERBASE_PROJECT_ID env var */\n projectId?: string;\n}\n\n/**\n * The native Browserbase session object returned by their SDK\n */\ntype BrowserbaseSession = Awaited<ReturnType<InstanceType<typeof Browserbase>['sessions']['create']>>;\n\n/**\n * Resolve config values from explicit config or environment variables\n */\nfunction resolveConfig(config: BrowserbaseConfig) {\n const apiKey = config.apiKey || (typeof process !== 'undefined' && process.env?.BROWSERBASE_API_KEY) || '';\n const projectId = config.projectId || (typeof process !== 'undefined' && process.env?.BROWSERBASE_PROJECT_ID) || '';\n\n if (!apiKey) {\n throw new Error(\n `Missing Browserbase API key. Provide 'apiKey' in config or set BROWSERBASE_API_KEY environment variable. ` +\n `Get your API key from https://www.browserbase.com/settings`\n );\n }\n\n return { apiKey, projectId };\n}\n\n/**\n * Create a Browserbase SDK client from config\n */\nfunction createClient(config: BrowserbaseConfig): Browserbase {\n const { apiKey } = resolveConfig(config);\n return new Browserbase({ apiKey });\n}\n\n/**\n * Map ComputeSDK session options to Browserbase create session params\n */\nfunction mapSessionOptions(config: BrowserbaseConfig, options?: CreateBrowserSessionOptions) {\n const { projectId } = resolveConfig(config);\n\n if (!options) {\n return projectId ? { projectId } : {};\n }\n\n const params: Record<string, any> = {};\n if (projectId) params.projectId = projectId;\n if (options.region) params.region = options.region;\n if (options.keepAlive !== undefined) params.keepAlive = options.keepAlive;\n if (options.timeout !== undefined) params.timeout = options.timeout;\n // Browserbase accepts a single extensionId per session\n if (options.extensionIds?.[0]) params.extensionId = options.extensionIds[0];\n if (options.userMetadata) params.userMetadata = options.userMetadata;\n\n // Proxy configuration\n if (options.proxies === true) {\n params.proxies = true;\n } else if (Array.isArray(options.proxies)) {\n params.proxies = options.proxies.map((p: any) => {\n if (p.type === 'custom' && p.server) {\n return {\n type: 'external' as const,\n server: p.server,\n username: p.username,\n password: p.password,\n domainPattern: p.domainPattern,\n };\n }\n return {\n type: 'browserbase' as const,\n geolocation: p.geolocation,\n domainPattern: p.domainPattern,\n };\n });\n }\n\n // Browser settings\n const browserSettings: Record<string, any> = {};\n if (options.viewport) browserSettings.viewport = options.viewport;\n if (options.stealth !== undefined) browserSettings.advancedStealth = options.stealth;\n if (options.recording !== undefined) browserSettings.recordSession = options.recording;\n if (options.logging !== undefined) browserSettings.logSession = options.logging;\n if (options.profileId) {\n browserSettings.context = { id: options.profileId, persist: true };\n }\n\n if (Object.keys(browserSettings).length > 0) {\n params.browserSettings = browserSettings;\n }\n\n return params;\n}\n\n/**\n * Normalize a Browserbase session into our standard shape\n */\nfunction normalizeSession(session: BrowserbaseSession) {\n return {\n session,\n sessionId: session.id,\n connectUrl: session.connectUrl,\n status: mapStatus(session.status),\n };\n}\n\nfunction mapStatus(status: string): 'created' | 'running' | 'completed' | 'failed' | 'timed_out' {\n switch (status) {\n case 'RUNNING': return 'running';\n case 'COMPLETED': return 'completed';\n case 'FAILED':\n case 'ERROR': return 'failed';\n case 'TIMED_OUT': return 'timed_out';\n default: return 'created';\n }\n}\n\n/**\n * Create a Browserbase browser provider instance\n *\n * @example\n * ```ts\n * import { browserbase } from '@computesdk/browserbase';\n *\n * const bb = browserbase({ apiKey: 'bb_live_...' });\n *\n * // Create a stealth browser session\n * const session = await bb.session.create({ stealth: true, proxies: true });\n * console.log(session.connectUrl);\n *\n * // Connect with Playwright\n * const browser = await chromium.connectOverCDP(session.connectUrl);\n * const page = browser.contexts()[0].pages()[0];\n * await page.goto('https://example.com');\n *\n * // Get session recording after\n * const recording = await session.getRecording();\n * ```\n */\nexport const browserbase = defineBrowserProvider<BrowserbaseSession, BrowserbaseConfig>({\n name: 'browserbase',\n methods: {\n // ─── Session Lifecycle ─────────────────────────────────────────────\n session: {\n create: async (config, options) => {\n const client = createClient(config);\n const params = mapSessionOptions(config, options);\n const session = await client.sessions.create(params);\n return normalizeSession(session);\n },\n\n getById: async (config, sessionId) => {\n const client = createClient(config);\n try {\n const session = await client.sessions.retrieve(sessionId);\n return normalizeSession(session as BrowserbaseSession);\n } catch {\n return null;\n }\n },\n\n list: async (config) => {\n const client = createClient(config);\n const response = await client.sessions.list();\n return (response as BrowserbaseSession[]).map(normalizeSession);\n },\n\n destroy: async (config, sessionId) => {\n const client = createClient(config);\n await client.sessions.update(sessionId, { status: 'REQUEST_RELEASE' });\n },\n\n getConnectUrl: async (config, sessionId) => {\n const client = createClient(config);\n const session = await client.sessions.retrieve(sessionId);\n return (session as BrowserbaseSession).connectUrl;\n },\n },\n\n // ─── Profiles (Browserbase Contexts) ───────────────────────────────\n profile: {\n create: async (config, options) => {\n const client = createClient(config);\n const { projectId } = resolveConfig(config);\n const result = await client.contexts.create(projectId ? { projectId } : {});\n return {\n profileId: result.id,\n name: options?.name,\n metadata: options?.metadata as Record<string, unknown> | undefined,\n } satisfies BrowserProfile;\n },\n\n get: async (config, profileId) => {\n const client = createClient(config);\n try {\n const result = await client.contexts.retrieve(profileId);\n return { profileId: result.id } satisfies BrowserProfile;\n } catch {\n return null;\n }\n },\n\n list: async (_config) => {\n // Browserbase API doesn't expose a list contexts endpoint\n // Return empty — users track their own context IDs\n return [];\n },\n\n delete: async (config, profileId) => {\n const client = createClient(config);\n await client.contexts.delete(profileId);\n },\n },\n\n // ─── Extensions ────────────────────────────────────────────────────\n extension: {\n create: async (config, options) => {\n const client = createClient(config);\n const blob = typeof options.file === 'string'\n ? new Blob([options.file])\n : new Blob([new Uint8Array(options.file).buffer as ArrayBuffer]);\n const file = new File([blob], options.name ?? 'extension.zip');\n const result = await client.extensions.create({ file });\n return {\n extensionId: result.id,\n name: options.name,\n } satisfies BrowserExtension;\n },\n\n get: async (config, extensionId) => {\n const client = createClient(config);\n try {\n const result = await client.extensions.retrieve(extensionId);\n return { extensionId: result.id } satisfies BrowserExtension;\n } catch {\n return null;\n }\n },\n\n delete: async (config, extensionId) => {\n const client = createClient(config);\n await client.extensions.delete(extensionId);\n },\n },\n\n // ─── Logs ──────────────────────────────────────────────────────────\n logs: {\n list: async (config, sessionId) => {\n const client = createClient(config);\n const response = await client.sessions.logs.list(sessionId);\n return (response as any[]).map(log => ({\n timestamp: new Date(log.timestamp),\n level: (log.level ?? 'info') as BrowserLog['level'],\n message: log.message ?? '',\n data: log.params,\n }));\n },\n },\n\n // ─── Recordings ────────────────────────────────────────────────────\n recording: {\n get: async (config, sessionId) => {\n const client = createClient(config);\n try {\n const data = await client.sessions.recording.retrieve(sessionId);\n return {\n recordingId: sessionId,\n sessionId,\n format: 'rrweb',\n data,\n } satisfies BrowserRecording;\n } catch {\n return null;\n }\n },\n },\n },\n});\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@computesdk/browserbase",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Browserbase browser provider for ComputeSDK - cloud browser sessions with stealth mode, proxies, and session replay",
|
|
5
|
+
"author": "Garrison",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "./dist/index.js",
|
|
9
|
+
"module": "./dist/index.mjs",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.mjs",
|
|
15
|
+
"require": "./dist/index.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist"
|
|
20
|
+
],
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@browserbasehq/sdk": "^2.0.0",
|
|
23
|
+
"dotenv": "^16.0.0",
|
|
24
|
+
"playwright-core": "^1.40.0",
|
|
25
|
+
"@computesdk/provider": "1.1.0",
|
|
26
|
+
"computesdk": "2.5.4"
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"computesdk",
|
|
30
|
+
"browserbase",
|
|
31
|
+
"browser",
|
|
32
|
+
"headless",
|
|
33
|
+
"playwright",
|
|
34
|
+
"puppeteer",
|
|
35
|
+
"stealth",
|
|
36
|
+
"proxy",
|
|
37
|
+
"provider"
|
|
38
|
+
],
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "https://github.com/computesdk/computesdk.git",
|
|
42
|
+
"directory": "packages/browserbase"
|
|
43
|
+
},
|
|
44
|
+
"homepage": "https://www.computesdk.com",
|
|
45
|
+
"bugs": {
|
|
46
|
+
"url": "https://github.com/computesdk/computesdk/issues"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@types/node": "^20.0.0",
|
|
50
|
+
"@vitest/coverage-v8": "^1.0.0",
|
|
51
|
+
"eslint": "^8.37.0",
|
|
52
|
+
"rimraf": "^5.0.0",
|
|
53
|
+
"tsup": "^8.0.0",
|
|
54
|
+
"typescript": "^5.0.0",
|
|
55
|
+
"vitest": "^1.0.0",
|
|
56
|
+
"@computesdk/test-utils": "1.6.1"
|
|
57
|
+
},
|
|
58
|
+
"scripts": {
|
|
59
|
+
"build": "tsup",
|
|
60
|
+
"clean": "rimraf dist",
|
|
61
|
+
"dev": "tsup --watch",
|
|
62
|
+
"test": "vitest run",
|
|
63
|
+
"test:watch": "vitest watch",
|
|
64
|
+
"test:coverage": "vitest run --coverage",
|
|
65
|
+
"typecheck": "tsc --noEmit",
|
|
66
|
+
"lint": "eslint"
|
|
67
|
+
}
|
|
68
|
+
}
|