diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4425e63..328f08f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,12 +7,17 @@ on: - 'integrated/**' - 'stl-preview-head/**' - 'stl-preview-base/**' + pull_request: + branches-ignore: + - 'stl-preview-head/**' + - 'stl-preview-base/**' jobs: lint: timeout-minutes: 10 name: lint runs-on: ${{ github.repository == 'stainless-sdks/browserbase-node' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - uses: actions/checkout@v4 @@ -31,6 +36,7 @@ jobs: timeout-minutes: 5 name: build runs-on: ${{ github.repository == 'stainless-sdks/browserbase-node' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + if: github.event_name == 'push' || github.event.pull_request.head.repo.fork permissions: contents: read id-token: write @@ -66,6 +72,7 @@ jobs: timeout-minutes: 10 name: test runs-on: ${{ github.repository == 'stainless-sdks/browserbase-node' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - uses: actions/checkout@v4 diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 69e82f1..6ed9c80 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "2.6.0" + ".": "2.7.0" } diff --git a/.stats.yml b/.stats.yml index 38c95a8..40aaa42 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 18 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fbrowserbase-e2ed1b5267eeff92982918505349017b9155da2c7ab948787ab11cf9068af1b8.yml -openapi_spec_hash: 6639c21dccb52ca610cae833227a9791 -config_hash: 74882e23a455dece33e43a27e67f0fbb +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fbrowserbase-219341ea9864a23d33fbb51843fd6f762f41ec8be5154bd963bfceff0bc30bb1.yml +openapi_spec_hash: 43fdb5f9ab7c52a17206c881128afb45 +config_hash: b3ca4ec5b02e5333af51ebc2e9fdef1b diff --git a/CHANGELOG.md b/CHANGELOG.md index e085bb8..0c9c1bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,38 @@ # Changelog +## 2.7.0 (2025-07-03) + +Full Changelog: [v2.6.0...v2.7.0](https://github.com/browserbase/sdk-node/compare/v2.6.0...v2.7.0) + +### Features + +* **api:** api update ([ef5f62b](https://github.com/browserbase/sdk-node/commit/ef5f62b267edcfa58fb677db40ae24a9a742ffa0)) +* **client:** add support for endpoint-specific base URLs ([0c69436](https://github.com/browserbase/sdk-node/commit/0c69436d731785b207af5f979e9eb5ae1b975957)) + + +### Bug Fixes + +* **ci:** release-doctor — report correct token name ([8e59beb](https://github.com/browserbase/sdk-node/commit/8e59beb314e8c07bd14b471121e28ec941168190)) +* **client:** don't send `Content-Type` for bodyless methods ([bfe46e8](https://github.com/browserbase/sdk-node/commit/bfe46e8c3af3377953857072ee39babdaec25820)) +* publish script — handle NPM errors correctly ([87c245e](https://github.com/browserbase/sdk-node/commit/87c245e2048dad1586d97fae8c4622c6e2780365)) + + +### Chores + +* **ci:** enable for pull requests ([132825d](https://github.com/browserbase/sdk-node/commit/132825d5c65ba9aa1c47afe9b8a7b14885129598)) +* **ci:** only run for pushes and fork pull requests ([a166050](https://github.com/browserbase/sdk-node/commit/a166050ab35ddff365ca60f23ed1243690b7eda2)) +* **docs:** grammar improvements ([985f2fe](https://github.com/browserbase/sdk-node/commit/985f2fe1bf866f1dc48c8d5f1827dda2e99b6f11)) +* **docs:** use top-level-await in example snippets ([24c7006](https://github.com/browserbase/sdk-node/commit/24c7006ca4c4dc7c03a48796b2677bdc47728934)) +* improve publish-npm script --latest tag logic ([88ce3e3](https://github.com/browserbase/sdk-node/commit/88ce3e3a96e34bfeb08d2ac254440b283818d7ef)) +* **internal:** make base APIResource abstract ([6ec9d38](https://github.com/browserbase/sdk-node/commit/6ec9d38a92775cb8e46468b05f539f53a01b54c9)) +* **internal:** version bump ([690777f](https://github.com/browserbase/sdk-node/commit/690777f5b88d363db563aba093363ed84c7c9ec4)) +* mention unit type in timeout docs ([8d864d1](https://github.com/browserbase/sdk-node/commit/8d864d1f6858a655840ec824434e045c886216eb)) + + +### Refactors + +* **types:** replace Record with mapped types ([3e0bfd3](https://github.com/browserbase/sdk-node/commit/3e0bfd327332edd2969106d189e650286d13e441)) + ## 2.6.0 (2025-05-16) Full Changelog: [v2.5.0...v2.6.0](https://github.com/browserbase/sdk-node/compare/v2.5.0...v2.6.0) diff --git a/README.md b/README.md index 5066f7f..4530dc1 100644 --- a/README.md +++ b/README.md @@ -26,13 +26,9 @@ const client = new Browserbase({ apiKey: process.env['BROWSERBASE_API_KEY'], // This is the default and can be omitted }); -async function main() { - const session = await client.sessions.create({ projectId: 'your_project_id' }); +const session = await client.sessions.create({ projectId: 'your_project_id' }); - console.log(session.id); -} - -main(); +console.log(session.id); ``` ### Request & Response types @@ -47,12 +43,8 @@ const client = new Browserbase({ apiKey: process.env['BROWSERBASE_API_KEY'], // This is the default and can be omitted }); -async function main() { - const params: Browserbase.SessionCreateParams = { projectId: 'your_project_id' }; - const session: Browserbase.SessionCreateResponse = await client.sessions.create(params); -} - -main(); +const params: Browserbase.SessionCreateParams = { projectId: 'your_project_id' }; +const session: Browserbase.SessionCreateResponse = await client.sessions.create(params); ``` Documentation for each method, request param, and response field are available in docstrings and will appear on hover in most modern editors. @@ -95,19 +87,15 @@ a subclass of `APIError` will be thrown: ```ts -async function main() { - const session = await client.sessions.create({ projectId: 'your_project_id' }).catch(async (err) => { - if (err instanceof Browserbase.APIError) { - console.log(err.status); // 400 - console.log(err.name); // BadRequestError - console.log(err.headers); // {server: 'nginx', ...} - } else { - throw err; - } - }); -} - -main(); +const session = await client.sessions.create({ projectId: 'your_project_id' }).catch(async (err) => { + if (err instanceof Browserbase.APIError) { + console.log(err.status); // 400 + console.log(err.name); // BadRequestError + console.log(err.headers); // {server: 'nginx', ...} + } else { + throw err; + } +}); ``` Error codes are as follows: diff --git a/SECURITY.md b/SECURITY.md index e10eb19..ad64e4b 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -16,11 +16,11 @@ before making any information public. ## Reporting Non-SDK Related Security Issues If you encounter security issues that are not directly related to SDKs but pertain to the services -or products provided by Browserbase please follow the respective company's security reporting guidelines. +or products provided by Browserbase, please follow the respective company's security reporting guidelines. ### Browserbase Terms and Policies -Please contact support@browserbase.com for any questions or concerns regarding security of our services. +Please contact support@browserbase.com for any questions or concerns regarding the security of our services. --- diff --git a/api.md b/api.md index 37226d3..5a0313d 100644 --- a/api.md +++ b/api.md @@ -2,59 +2,60 @@ Types: -- Context - ContextCreateResponse +- ContextRetrieveResponse - ContextUpdateResponse Methods: - client.contexts.create({ ...params }) -> ContextCreateResponse -- client.contexts.retrieve(id) -> Context +- client.contexts.retrieve(id) -> ContextRetrieveResponse - client.contexts.update(id) -> ContextUpdateResponse # Extensions Types: -- Extension +- ExtensionCreateResponse +- ExtensionRetrieveResponse Methods: -- client.extensions.create({ ...params }) -> Extension -- client.extensions.retrieve(id) -> Extension +- client.extensions.create({ ...params }) -> ExtensionCreateResponse +- client.extensions.retrieve(id) -> ExtensionRetrieveResponse - client.extensions.delete(id) -> void # Projects Types: -- Project -- ProjectUsage +- ProjectRetrieveResponse - ProjectListResponse +- ProjectUsageResponse Methods: -- client.projects.retrieve(id) -> Project +- client.projects.retrieve(id) -> ProjectRetrieveResponse - client.projects.list() -> ProjectListResponse -- client.projects.usage(id) -> ProjectUsage +- client.projects.usage(id) -> ProjectUsageResponse # Sessions Types: -- Session -- SessionLiveURLs - SessionCreateResponse - SessionRetrieveResponse +- SessionUpdateResponse - SessionListResponse +- SessionDebugResponse Methods: - client.sessions.create({ ...params }) -> SessionCreateResponse - client.sessions.retrieve(id) -> SessionRetrieveResponse -- client.sessions.update(id, { ...params }) -> Session +- client.sessions.update(id, { ...params }) -> SessionUpdateResponse - client.sessions.list({ ...params }) -> SessionListResponse -- client.sessions.debug(id) -> SessionLiveURLs +- client.sessions.debug(id) -> SessionDebugResponse ## Downloads @@ -66,7 +67,6 @@ Methods: Types: -- SessionLog - LogListResponse Methods: @@ -77,7 +77,6 @@ Methods: Types: -- SessionRecording - RecordingRetrieveResponse Methods: diff --git a/bin/check-release-environment b/bin/check-release-environment index 3098216..e4b6d58 100644 --- a/bin/check-release-environment +++ b/bin/check-release-environment @@ -3,7 +3,7 @@ errors=() if [ -z "${NPM_TOKEN}" ]; then - errors+=("The BROWSERBASE_NPM_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets") + errors+=("The NPM_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets") fi lenErrors=${#errors[@]} diff --git a/bin/publish-npm b/bin/publish-npm index 4c21181..fa2243d 100644 --- a/bin/publish-npm +++ b/bin/publish-npm @@ -4,19 +4,55 @@ set -eux npm config set '//registry.npmjs.org/:_authToken' "$NPM_TOKEN" -# Build the project yarn build - -# Navigate to the dist directory cd dist -# Get the version from package.json -VERSION="$(node -p "require('./package.json').version")" +# Get package name and version from package.json +PACKAGE_NAME="$(jq -r -e '.name' ./package.json)" +VERSION="$(jq -r -e '.version' ./package.json)" + +# Get latest version from npm +# +# If the package doesn't exist, npm will return: +# { +# "error": { +# "code": "E404", +# "summary": "Unpublished on 2025-06-05T09:54:53.528Z", +# "detail": "'the_package' is not in this registry..." +# } +# } +NPM_INFO="$(npm view "$PACKAGE_NAME" version --json 2>/dev/null || true)" + +# Check if we got an E404 error +if echo "$NPM_INFO" | jq -e '.error.code == "E404"' > /dev/null 2>&1; then + # Package doesn't exist yet, no last version + LAST_VERSION="" +elif echo "$NPM_INFO" | jq -e '.error' > /dev/null 2>&1; then + # Report other errors + echo "ERROR: npm returned unexpected data:" + echo "$NPM_INFO" + exit 1 +else + # Success - get the version + LAST_VERSION=$(echo "$NPM_INFO" | jq -r '.') # strip quotes +fi -# Extract the pre-release tag if it exists +# Check if current version is pre-release (e.g. alpha / beta / rc) +CURRENT_IS_PRERELEASE=false if [[ "$VERSION" =~ -([a-zA-Z]+) ]]; then - # Extract the part before any dot in the pre-release identifier - TAG="${BASH_REMATCH[1]}" + CURRENT_IS_PRERELEASE=true + CURRENT_TAG="${BASH_REMATCH[1]}" +fi + +# Check if last version is a stable release +LAST_IS_STABLE_RELEASE=true +if [[ -z "$LAST_VERSION" || "$LAST_VERSION" =~ -([a-zA-Z]+) ]]; then + LAST_IS_STABLE_RELEASE=false +fi + +# Use a corresponding alpha/beta tag if there already is a stable release and we're publishing a prerelease. +if $CURRENT_IS_PRERELEASE && $LAST_IS_STABLE_RELEASE; then + TAG="$CURRENT_TAG" else TAG="latest" fi diff --git a/package-lock.json b/package-lock.json index 4edad49..03380ab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@browserbasehq/sdk", - "version": "2.6.0", + "version": "2.7.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@browserbasehq/sdk", - "version": "2.6.0", + "version": "2.7.0", "dependencies": { "@types/node": "^18.11.18", "@types/node-fetch": "^2.6.4", diff --git a/package.json b/package.json index 39c08ec..191d760 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@browserbasehq/sdk", - "version": "2.6.0", + "version": "2.7.0", "description": "The official Node.js library for the Browserbase API", "author": "Browserbase ", "types": "dist/index.d.ts", diff --git a/scripts/build b/scripts/build index 304bc38..2723a3f 100755 --- a/scripts/build +++ b/scripts/build @@ -28,7 +28,7 @@ fi node scripts/utils/make-dist-package-json.cjs > dist/package.json # build to .js/.mjs/.d.ts files -npm exec tsc-multi +./node_modules/.bin/tsc-multi # copy over handwritten .js/.mjs/.d.ts files cp src/_shims/*.{d.ts,js,mjs,md} dist/_shims cp src/_shims/auto/*.{d.ts,js,mjs} dist/_shims/auto diff --git a/src/core.ts b/src/core.ts index 180db7d..f4717df 100644 --- a/src/core.ts +++ b/src/core.ts @@ -170,6 +170,7 @@ export class APIPromise extends Promise { export abstract class APIClient { baseURL: string; + #baseURLOverridden: boolean; maxRetries: number; timeout: number; httpAgent: Agent | undefined; @@ -179,18 +180,21 @@ export abstract class APIClient { constructor({ baseURL, + baseURLOverridden, maxRetries = 2, timeout = 60000, // 1 minute httpAgent, fetch: overriddenFetch, }: { baseURL: string; + baseURLOverridden: boolean; maxRetries?: number | undefined; timeout: number | undefined; httpAgent: Agent | undefined; fetch: Fetch | undefined; }) { this.baseURL = baseURL; + this.#baseURLOverridden = baseURLOverridden; this.maxRetries = validatePositiveInteger('maxRetries', maxRetries); this.timeout = validatePositiveInteger('timeout', timeout); this.httpAgent = httpAgent; @@ -213,7 +217,7 @@ export abstract class APIClient { protected defaultHeaders(opts: FinalRequestOptions): Headers { return { Accept: 'application/json', - 'Content-Type': 'application/json', + ...(['head', 'get'].includes(opts.method) ? {} : { 'Content-Type': 'application/json' }), 'User-Agent': this.getUserAgent(), ...getPlatformHeaders(), ...this.authHeaders(opts), @@ -300,7 +304,7 @@ export abstract class APIClient { { retryCount = 0 }: { retryCount?: number } = {}, ): { req: RequestInit; url: string; timeout: number } { const options = { ...inputOptions }; - const { method, path, query, headers: headers = {} } = options; + const { method, path, query, defaultBaseURL, headers: headers = {} } = options; const body = ArrayBuffer.isView(options.body) || (options.__binaryRequest && typeof options.body === 'string') ? @@ -310,7 +314,7 @@ export abstract class APIClient { : null; const contentLength = this.calculateContentLength(body); - const url = this.buildURL(path!, query); + const url = this.buildURL(path!, query, defaultBaseURL); if ('timeout' in options) validatePositiveInteger('timeout', options.timeout); options.timeout = options.timeout ?? this.timeout; const httpAgent = options.httpAgent ?? this.httpAgent ?? getDefaultAgent(url); @@ -503,11 +507,12 @@ export abstract class APIClient { return new PagePromise(this, request, Page); } - buildURL(path: string, query: Req | null | undefined): string { + buildURL(path: string, query: Req | null | undefined, defaultBaseURL?: string | undefined): string { + const baseURL = (!this.#baseURLOverridden && defaultBaseURL) || this.baseURL; const url = isAbsoluteURL(path) ? new URL(path) - : new URL(this.baseURL + (this.baseURL.endsWith('/') && path.startsWith('/') ? path.slice(1) : path)); + : new URL(baseURL + (baseURL.endsWith('/') && path.startsWith('/') ? path.slice(1) : path)); const defaultQuery = this.defaultQuery(); if (!isEmptyObj(defaultQuery)) { @@ -792,6 +797,7 @@ export type RequestOptions< query?: Req | undefined; body?: Req | null | undefined; headers?: Headers | undefined; + defaultBaseURL?: string | undefined; maxRetries?: number; stream?: boolean | undefined; @@ -813,6 +819,7 @@ const requestOptionsKeys: KeysEnum = { query: true, body: true, headers: true, + defaultBaseURL: true, maxRetries: true, stream: true, diff --git a/src/index.ts b/src/index.ts index 594b6a0..bbb432b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,23 +6,33 @@ import * as Errors from './error'; import * as Uploads from './uploads'; import * as API from './resources/index'; import { - Context, ContextCreateParams, ContextCreateResponse, + ContextRetrieveResponse, ContextUpdateResponse, Contexts, } from './resources/contexts'; -import { Extension, ExtensionCreateParams, Extensions } from './resources/extensions'; -import { Project, ProjectListResponse, ProjectUsage, Projects } from './resources/projects'; import { - Session, + ExtensionCreateParams, + ExtensionCreateResponse, + ExtensionRetrieveResponse, + Extensions, +} from './resources/extensions'; +import { + ProjectListResponse, + ProjectRetrieveResponse, + ProjectUsageResponse, + Projects, +} from './resources/projects'; +import { SessionCreateParams, SessionCreateResponse, + SessionDebugResponse, SessionListParams, SessionListResponse, - SessionLiveURLs, SessionRetrieveResponse, SessionUpdateParams, + SessionUpdateResponse, Sessions, } from './resources/sessions/sessions'; @@ -45,6 +55,8 @@ export interface ClientOptions { * * Note that request timeouts are retried by default, so in a worst-case scenario you may wait * much longer than this timeout before the promise succeeds or fails. + * + * @unit milliseconds */ timeout?: number | undefined; @@ -128,6 +140,7 @@ export class Browserbase extends Core.APIClient { super({ baseURL: options.baseURL!, + baseURLOverridden: baseURL ? baseURL !== 'https://api.browserbase.com' : false, timeout: options.timeout ?? 60000 /* 1 minute */, httpAgent: options.httpAgent, maxRetries: options.maxRetries, @@ -144,6 +157,13 @@ export class Browserbase extends Core.APIClient { projects: API.Projects = new API.Projects(this); sessions: API.Sessions = new API.Sessions(this); + /** + * Check whether the base URL is set to its default. + */ + #baseURLOverridden(): boolean { + return this.baseURL !== 'https://api.browserbase.com'; + } + protected override defaultQuery(): Core.DefaultQuery | undefined { return this._options.defaultQuery; } @@ -189,32 +209,33 @@ export declare namespace Browserbase { export { Contexts as Contexts, - type Context as Context, type ContextCreateResponse as ContextCreateResponse, + type ContextRetrieveResponse as ContextRetrieveResponse, type ContextUpdateResponse as ContextUpdateResponse, type ContextCreateParams as ContextCreateParams, }; export { Extensions as Extensions, - type Extension as Extension, + type ExtensionCreateResponse as ExtensionCreateResponse, + type ExtensionRetrieveResponse as ExtensionRetrieveResponse, type ExtensionCreateParams as ExtensionCreateParams, }; export { Projects as Projects, - type Project as Project, - type ProjectUsage as ProjectUsage, + type ProjectRetrieveResponse as ProjectRetrieveResponse, type ProjectListResponse as ProjectListResponse, + type ProjectUsageResponse as ProjectUsageResponse, }; export { Sessions as Sessions, - type Session as Session, - type SessionLiveURLs as SessionLiveURLs, type SessionCreateResponse as SessionCreateResponse, type SessionRetrieveResponse as SessionRetrieveResponse, + type SessionUpdateResponse as SessionUpdateResponse, type SessionListResponse as SessionListResponse, + type SessionDebugResponse as SessionDebugResponse, type SessionCreateParams as SessionCreateParams, type SessionUpdateParams as SessionUpdateParams, type SessionListParams as SessionListParams, diff --git a/src/resource.ts b/src/resource.ts index 36c4573..0fa4172 100644 --- a/src/resource.ts +++ b/src/resource.ts @@ -2,7 +2,7 @@ import type { Browserbase } from './index'; -export class APIResource { +export abstract class APIResource { protected _client: Browserbase; constructor(client: Browserbase) { diff --git a/src/resources/contexts.ts b/src/resources/contexts.ts index 884cdab..f8cc77a 100644 --- a/src/resources/contexts.ts +++ b/src/resources/contexts.ts @@ -12,33 +12,20 @@ export class Contexts extends APIResource { } /** - * Context + * Get a Context */ - retrieve(id: string, options?: Core.RequestOptions): Core.APIPromise { + retrieve(id: string, options?: Core.RequestOptions): Core.APIPromise { return this._client.get(`/v1/contexts/${id}`, options); } /** - * Update Context + * Update a Context */ update(id: string, options?: Core.RequestOptions): Core.APIPromise { return this._client.put(`/v1/contexts/${id}`, options); } } -export interface Context { - id: string; - - createdAt: string; - - /** - * The Project ID linked to the uploaded Context. - */ - projectId: string; - - updatedAt: string; -} - export interface ContextCreateResponse { id: string; @@ -65,6 +52,19 @@ export interface ContextCreateResponse { uploadUrl: string; } +export interface ContextRetrieveResponse { + id: string; + + createdAt: string; + + /** + * The Project ID linked to the uploaded Context. + */ + projectId: string; + + updatedAt: string; +} + export interface ContextUpdateResponse { id: string; @@ -101,8 +101,8 @@ export interface ContextCreateParams { export declare namespace Contexts { export { - type Context as Context, type ContextCreateResponse as ContextCreateResponse, + type ContextRetrieveResponse as ContextRetrieveResponse, type ContextUpdateResponse as ContextUpdateResponse, type ContextCreateParams as ContextCreateParams, }; diff --git a/src/resources/extensions.ts b/src/resources/extensions.ts index 857349f..9c607b8 100644 --- a/src/resources/extensions.ts +++ b/src/resources/extensions.ts @@ -7,19 +7,22 @@ export class Extensions extends APIResource { /** * Upload an Extension */ - create(body: ExtensionCreateParams, options?: Core.RequestOptions): Core.APIPromise { + create( + body: ExtensionCreateParams, + options?: Core.RequestOptions, + ): Core.APIPromise { return this._client.post('/v1/extensions', Core.multipartFormRequestOptions({ body, ...options })); } /** - * Extension + * Get an Extension */ - retrieve(id: string, options?: Core.RequestOptions): Core.APIPromise { + retrieve(id: string, options?: Core.RequestOptions): Core.APIPromise { return this._client.get(`/v1/extensions/${id}`, options); } /** - * Delete Extension + * Delete an Extension */ delete(id: string, options?: Core.RequestOptions): Core.APIPromise { return this._client.delete(`/v1/extensions/${id}`, { @@ -29,7 +32,22 @@ export class Extensions extends APIResource { } } -export interface Extension { +export interface ExtensionCreateResponse { + id: string; + + createdAt: string; + + fileName: string; + + /** + * The Project ID linked to the uploaded Extension. + */ + projectId: string; + + updatedAt: string; +} + +export interface ExtensionRetrieveResponse { id: string; createdAt: string; @@ -49,5 +67,9 @@ export interface ExtensionCreateParams { } export declare namespace Extensions { - export { type Extension as Extension, type ExtensionCreateParams as ExtensionCreateParams }; + export { + type ExtensionCreateResponse as ExtensionCreateResponse, + type ExtensionRetrieveResponse as ExtensionRetrieveResponse, + type ExtensionCreateParams as ExtensionCreateParams, + }; } diff --git a/src/resources/index.ts b/src/resources/index.ts index 96c5a42..959332a 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -2,20 +2,30 @@ export { Contexts, - type Context, type ContextCreateResponse, + type ContextRetrieveResponse, type ContextUpdateResponse, type ContextCreateParams, } from './contexts'; -export { Extensions, type Extension, type ExtensionCreateParams } from './extensions'; -export { Projects, type Project, type ProjectUsage, type ProjectListResponse } from './projects'; +export { + Extensions, + type ExtensionCreateResponse, + type ExtensionRetrieveResponse, + type ExtensionCreateParams, +} from './extensions'; +export { + Projects, + type ProjectRetrieveResponse, + type ProjectListResponse, + type ProjectUsageResponse, +} from './projects'; export { Sessions, - type Session, - type SessionLiveURLs, type SessionCreateResponse, type SessionRetrieveResponse, + type SessionUpdateResponse, type SessionListResponse, + type SessionDebugResponse, type SessionCreateParams, type SessionUpdateParams, type SessionListParams, diff --git a/src/resources/projects.ts b/src/resources/projects.ts index 236872f..9709cc5 100644 --- a/src/resources/projects.ts +++ b/src/resources/projects.ts @@ -5,28 +5,28 @@ import * as Core from '../core'; export class Projects extends APIResource { /** - * Project + * Get a Project */ - retrieve(id: string, options?: Core.RequestOptions): Core.APIPromise { + retrieve(id: string, options?: Core.RequestOptions): Core.APIPromise { return this._client.get(`/v1/projects/${id}`, options); } /** - * List projects + * List Projects */ list(options?: Core.RequestOptions): Core.APIPromise { return this._client.get('/v1/projects', options); } /** - * Project Usage + * Get Project Usage */ - usage(id: string, options?: Core.RequestOptions): Core.APIPromise { + usage(id: string, options?: Core.RequestOptions): Core.APIPromise { return this._client.get(`/v1/projects/${id}/usage`, options); } } -export interface Project { +export interface ProjectRetrieveResponse { id: string; /** @@ -45,18 +45,39 @@ export interface Project { updatedAt: string; } -export interface ProjectUsage { +export type ProjectListResponse = Array; + +export namespace ProjectListResponse { + export interface ProjectListResponseItem { + id: string; + + /** + * The maximum number of sessions that this project can run concurrently. + */ + concurrency: number; + + createdAt: string; + + defaultTimeout: number; + + name: string; + + ownerId: string; + + updatedAt: string; + } +} + +export interface ProjectUsageResponse { browserMinutes: number; proxyBytes: number; } -export type ProjectListResponse = Array; - export declare namespace Projects { export { - type Project as Project, - type ProjectUsage as ProjectUsage, + type ProjectRetrieveResponse as ProjectRetrieveResponse, type ProjectListResponse as ProjectListResponse, + type ProjectUsageResponse as ProjectUsageResponse, }; } diff --git a/src/resources/sessions/index.ts b/src/resources/sessions/index.ts index 9c9a61e..bb17bf0 100644 --- a/src/resources/sessions/index.ts +++ b/src/resources/sessions/index.ts @@ -1,15 +1,15 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. export { Downloads } from './downloads'; -export { Logs, type SessionLog, type LogListResponse } from './logs'; -export { Recording, type SessionRecording, type RecordingRetrieveResponse } from './recording'; +export { Logs, type LogListResponse } from './logs'; +export { Recording, type RecordingRetrieveResponse } from './recording'; export { Sessions, - type Session, - type SessionLiveURLs, type SessionCreateResponse, type SessionRetrieveResponse, + type SessionUpdateResponse, type SessionListResponse, + type SessionDebugResponse, type SessionCreateParams, type SessionUpdateParams, type SessionListParams, diff --git a/src/resources/sessions/logs.ts b/src/resources/sessions/logs.ts index 4a67cc6..feef0e5 100644 --- a/src/resources/sessions/logs.ts +++ b/src/resources/sessions/logs.ts @@ -12,32 +12,23 @@ export class Logs extends APIResource { } } -export interface SessionLog { - method: string; +export type LogListResponse = Array; - pageId: number; +export namespace LogListResponse { + export interface LogListResponseItem { + method: string; - sessionId: string; + pageId: number; - frameId?: string; + sessionId: string; - loaderId?: string; + frameId?: string; - request?: SessionLog.Request; + loaderId?: string; - response?: SessionLog.Response; + request?: LogListResponseItem.Request; - /** - * milliseconds that have elapsed since the UNIX epoch - */ - timestamp?: number; -} - -export namespace SessionLog { - export interface Request { - params: Record; - - rawBody: string; + response?: LogListResponseItem.Response; /** * milliseconds that have elapsed since the UNIX epoch @@ -45,20 +36,31 @@ export namespace SessionLog { timestamp?: number; } - export interface Response { - rawBody: string; + export namespace LogListResponseItem { + export interface Request { + params: { [key: string]: unknown }; - result: Record; + rawBody: string; - /** - * milliseconds that have elapsed since the UNIX epoch - */ - timestamp?: number; + /** + * milliseconds that have elapsed since the UNIX epoch + */ + timestamp?: number; + } + + export interface Response { + rawBody: string; + + result: { [key: string]: unknown }; + + /** + * milliseconds that have elapsed since the UNIX epoch + */ + timestamp?: number; + } } } -export type LogListResponse = Array; - export declare namespace Logs { - export { type SessionLog as SessionLog, type LogListResponse as LogListResponse }; + export { type LogListResponse as LogListResponse }; } diff --git a/src/resources/sessions/recording.ts b/src/resources/sessions/recording.ts index feb056f..7572517 100644 --- a/src/resources/sessions/recording.ts +++ b/src/resources/sessions/recording.ts @@ -12,28 +12,27 @@ export class Recording extends APIResource { } } -export interface SessionRecording { - /** - * See - * [rrweb documentation](https://github.com/rrweb-io/rrweb/blob/master/docs/recipes/dive-into-event.md). - */ - data: Record; +export type RecordingRetrieveResponse = Array; - sessionId: string; +export namespace RecordingRetrieveResponse { + export interface RecordingRetrieveResponseItem { + /** + * See + * [rrweb documentation](https://github.com/rrweb-io/rrweb/blob/master/docs/recipes/dive-into-event.md). + */ + data: { [key: string]: unknown }; - /** - * milliseconds that have elapsed since the UNIX epoch - */ - timestamp: number; + sessionId: string; - type: number; -} + /** + * milliseconds that have elapsed since the UNIX epoch + */ + timestamp: number; -export type RecordingRetrieveResponse = Array; + type: number; + } +} export declare namespace Recording { - export { - type SessionRecording as SessionRecording, - type RecordingRetrieveResponse as RecordingRetrieveResponse, - }; + export { type RecordingRetrieveResponse as RecordingRetrieveResponse }; } diff --git a/src/resources/sessions/sessions.ts b/src/resources/sessions/sessions.ts index 8e9c6d0..d97bea8 100644 --- a/src/resources/sessions/sessions.ts +++ b/src/resources/sessions/sessions.ts @@ -6,9 +6,9 @@ import * as Core from '../../core'; import * as DownloadsAPI from './downloads'; import { Downloads } from './downloads'; import * as LogsAPI from './logs'; -import { LogListResponse, Logs, SessionLog } from './logs'; +import { LogListResponse, Logs } from './logs'; import * as RecordingAPI from './recording'; -import { Recording, RecordingRetrieveResponse, SessionRecording } from './recording'; +import { Recording, RecordingRetrieveResponse } from './recording'; import * as UploadsAPI from './uploads'; import { UploadCreateParams, UploadCreateResponse, Uploads } from './uploads'; @@ -26,16 +26,20 @@ export class Sessions extends APIResource { } /** - * Session + * Get a Session */ retrieve(id: string, options?: Core.RequestOptions): Core.APIPromise { return this._client.get(`/v1/sessions/${id}`, options); } /** - * Update Session + * Update a Session */ - update(id: string, body: SessionUpdateParams, options?: Core.RequestOptions): Core.APIPromise { + update( + id: string, + body: SessionUpdateParams, + options?: Core.RequestOptions, + ): Core.APIPromise { return this._client.post(`/v1/sessions/${id}`, { body, ...options }); } @@ -57,14 +61,19 @@ export class Sessions extends APIResource { /** * Session Live URLs */ - debug(id: string, options?: Core.RequestOptions): Core.APIPromise { + debug(id: string, options?: Core.RequestOptions): Core.APIPromise { return this._client.get(`/v1/sessions/${id}/debug`, options); } } -export interface Session { +export interface SessionCreateResponse { id: string; + /** + * WebSocket URL to connect to the Session. + */ + connectUrl: string; + createdAt: string; expiresAt: string; @@ -89,6 +98,16 @@ export interface Session { */ region: 'us-west-2' | 'us-east-1' | 'eu-central-1' | 'ap-southeast-1'; + /** + * HTTP URL to connect to the Session. + */ + seleniumRemoteUrl: string; + + /** + * Signing key to use when connecting to the Session via HTTP. + */ + signingKey: string; + startedAt: string; status: 'RUNNING' | 'ERROR' | 'TIMED_OUT' | 'COMPLETED'; @@ -116,43 +135,12 @@ export interface Session { * Arbitrary user metadata to attach to the session. To learn more about user * metadata, see [User Metadata](/features/sessions#user-metadata). */ - userMetadata?: Record; -} - -export interface SessionLiveURLs { - debuggerFullscreenUrl: string; - - debuggerUrl: string; - - pages: Array; - - wsUrl: string; -} - -export namespace SessionLiveURLs { - export interface Page { - id: string; - - debuggerFullscreenUrl: string; - - debuggerUrl: string; - - faviconUrl: string; - - title: string; - - url: string; - } + userMetadata?: { [key: string]: unknown }; } -export interface SessionCreateResponse { +export interface SessionRetrieveResponse { id: string; - /** - * WebSocket URL to connect to the Session. - */ - connectUrl: string; - createdAt: string; expiresAt: string; @@ -177,16 +165,6 @@ export interface SessionCreateResponse { */ region: 'us-west-2' | 'us-east-1' | 'eu-central-1' | 'ap-southeast-1'; - /** - * HTTP URL to connect to the Session. - */ - seleniumRemoteUrl: string; - - /** - * Signing key to use when connecting to the Session via HTTP. - */ - signingKey: string; - startedAt: string; status: 'RUNNING' | 'ERROR' | 'TIMED_OUT' | 'COMPLETED'; @@ -198,6 +176,11 @@ export interface SessionCreateResponse { */ avgCpuUsage?: number; + /** + * WebSocket URL to connect to the Session. + */ + connectUrl?: string; + /** * Optional. The Context linked to the Session. */ @@ -210,14 +193,24 @@ export interface SessionCreateResponse { */ memoryUsage?: number; + /** + * HTTP URL to connect to the Session. + */ + seleniumRemoteUrl?: string; + + /** + * Signing key to use when connecting to the Session via HTTP. + */ + signingKey?: string; + /** * Arbitrary user metadata to attach to the session. To learn more about user * metadata, see [User Metadata](/features/sessions#user-metadata). */ - userMetadata?: Record; + userMetadata?: { [key: string]: unknown }; } -export interface SessionRetrieveResponse { +export interface SessionUpdateResponse { id: string; createdAt: string; @@ -255,11 +248,6 @@ export interface SessionRetrieveResponse { */ avgCpuUsage?: number; - /** - * WebSocket URL to connect to the Session. - */ - connectUrl?: string; - /** * Optional. The Context linked to the Session. */ @@ -272,24 +260,99 @@ export interface SessionRetrieveResponse { */ memoryUsage?: number; - /** - * HTTP URL to connect to the Session. - */ - seleniumRemoteUrl?: string; - - /** - * Signing key to use when connecting to the Session via HTTP. - */ - signingKey?: string; - /** * Arbitrary user metadata to attach to the session. To learn more about user * metadata, see [User Metadata](/features/sessions#user-metadata). */ - userMetadata?: Record; + userMetadata?: { [key: string]: unknown }; } -export type SessionListResponse = Array; +export type SessionListResponse = Array; + +export namespace SessionListResponse { + export interface SessionListResponseItem { + id: string; + + createdAt: string; + + expiresAt: string; + + /** + * Indicates if the Session was created to be kept alive upon disconnections + */ + keepAlive: boolean; + + /** + * The Project ID linked to the Session. + */ + projectId: string; + + /** + * Bytes used via the [Proxy](/features/stealth-mode#proxies-and-residential-ips) + */ + proxyBytes: number; + + /** + * The region where the Session is running. + */ + region: 'us-west-2' | 'us-east-1' | 'eu-central-1' | 'ap-southeast-1'; + + startedAt: string; + + status: 'RUNNING' | 'ERROR' | 'TIMED_OUT' | 'COMPLETED'; + + updatedAt: string; + + /** + * CPU used by the Session + */ + avgCpuUsage?: number; + + /** + * Optional. The Context linked to the Session. + */ + contextId?: string; + + endedAt?: string; + + /** + * Memory used by the Session + */ + memoryUsage?: number; + + /** + * Arbitrary user metadata to attach to the session. To learn more about user + * metadata, see [User Metadata](/features/sessions#user-metadata). + */ + userMetadata?: { [key: string]: unknown }; + } +} + +export interface SessionDebugResponse { + debuggerFullscreenUrl: string; + + debuggerUrl: string; + + pages: Array; + + wsUrl: string; +} + +export namespace SessionDebugResponse { + export interface Page { + id: string; + + debuggerFullscreenUrl: string; + + debuggerUrl: string; + + faviconUrl: string; + + title: string; + + url: string; + } +} export interface SessionCreateParams { /** @@ -316,9 +379,7 @@ export interface SessionCreateParams { * Proxy configuration. Can be true for default proxy, or an array of proxy * configurations. */ - proxies?: - | boolean - | Array; + proxies?: Array | boolean; /** * The region where the Session should run. @@ -335,7 +396,7 @@ export interface SessionCreateParams { * Arbitrary user metadata to attach to the session. To learn more about user * metadata, see [User Metadata](/features/sessions#user-metadata). */ - userMetadata?: Record; + userMetadata?: { [key: string]: unknown }; } export namespace SessionCreateParams { @@ -370,10 +431,6 @@ export namespace SessionCreateParams { */ extensionId?: string; - /** - * See usage examples - * [in the Stealth Mode page](/features/stealth-mode#fingerprinting). - */ fingerprint?: BrowserSettings.Fingerprint; /** @@ -407,10 +464,6 @@ export namespace SessionCreateParams { persist?: boolean; } - /** - * See usage examples - * [in the Stealth Mode page](/features/stealth-mode#fingerprinting). - */ export interface Fingerprint { browsers?: Array<'chrome' | 'edge' | 'firefox' | 'safari'>; @@ -418,16 +471,8 @@ export namespace SessionCreateParams { httpVersion?: '1' | '2'; - /** - * Full list of locales is available - * [here](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language). - */ locales?: Array; - /** - * Note: `operatingSystems` set to `ios` or `android` requires `devices` to include - * `"mobile"`. - */ operatingSystems?: Array<'android' | 'ios' | 'linux' | 'macos' | 'windows'>; screen?: Fingerprint.Screen; @@ -435,24 +480,30 @@ export namespace SessionCreateParams { export namespace Fingerprint { export interface Screen { - maxHeight?: number; + maxHeight: number; - maxWidth?: number; + maxWidth: number; - minHeight?: number; + minHeight: number; - minWidth?: number; + minWidth: number; } } export interface Viewport { + /** + * The height of the browser. + */ height?: number; + /** + * The width of the browser. + */ width?: number; } } - export interface BrowserbaseProxyConfig { + export interface UnionMember0 { /** * Type of proxy. Always use 'browserbase' for the Browserbase managed proxy * network. @@ -466,14 +517,14 @@ export namespace SessionCreateParams { domainPattern?: string; /** - * Configuration for geolocation + * Geographic location for the proxy. Optional. */ - geolocation?: BrowserbaseProxyConfig.Geolocation; + geolocation?: UnionMember0.Geolocation; } - export namespace BrowserbaseProxyConfig { + export namespace UnionMember0 { /** - * Configuration for geolocation + * Geographic location for the proxy. Optional. */ export interface Geolocation { /** @@ -493,7 +544,7 @@ export namespace SessionCreateParams { } } - export interface ExternalProxyConfig { + export interface UnionMember1 { /** * Server URL for external proxy. Required. */ @@ -554,11 +605,11 @@ Sessions.Uploads = Uploads; export declare namespace Sessions { export { - type Session as Session, - type SessionLiveURLs as SessionLiveURLs, type SessionCreateResponse as SessionCreateResponse, type SessionRetrieveResponse as SessionRetrieveResponse, + type SessionUpdateResponse as SessionUpdateResponse, type SessionListResponse as SessionListResponse, + type SessionDebugResponse as SessionDebugResponse, type SessionCreateParams as SessionCreateParams, type SessionUpdateParams as SessionUpdateParams, type SessionListParams as SessionListParams, @@ -566,13 +617,9 @@ export declare namespace Sessions { export { Downloads as Downloads }; - export { Logs as Logs, type SessionLog as SessionLog, type LogListResponse as LogListResponse }; + export { Logs as Logs, type LogListResponse as LogListResponse }; - export { - Recording as Recording, - type SessionRecording as SessionRecording, - type RecordingRetrieveResponse as RecordingRetrieveResponse, - }; + export { Recording as Recording, type RecordingRetrieveResponse as RecordingRetrieveResponse }; export { Uploads as Uploads, diff --git a/src/version.ts b/src/version.ts index cc6e4a8..9556c21 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '2.6.0'; // x-release-please-version +export const VERSION = '2.7.0'; // x-release-please-version diff --git a/tests/api-resources/contexts.test.ts b/tests/api-resources/contexts.test.ts index 1f12d89..ba6cbb6 100644 --- a/tests/api-resources/contexts.test.ts +++ b/tests/api-resources/contexts.test.ts @@ -10,7 +10,7 @@ const client = new Browserbase({ describe('resource contexts', () => { test('create: only required params', async () => { - const responsePromise = client.contexts.create({ projectId: 'projectId' }); + const responsePromise = client.contexts.create({ projectId: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -21,11 +21,11 @@ describe('resource contexts', () => { }); test('create: required and optional params', async () => { - const response = await client.contexts.create({ projectId: 'projectId' }); + const response = await client.contexts.create({ projectId: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e' }); }); test('retrieve', async () => { - const responsePromise = client.contexts.retrieve('id'); + const responsePromise = client.contexts.retrieve('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -37,13 +37,13 @@ describe('resource contexts', () => { test('retrieve: request options instead of params are passed correctly', async () => { // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect(client.contexts.retrieve('id', { path: '/_stainless_unknown_path' })).rejects.toThrow( - Browserbase.NotFoundError, - ); + await expect( + client.contexts.retrieve('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { path: '/_stainless_unknown_path' }), + ).rejects.toThrow(Browserbase.NotFoundError); }); test('update', async () => { - const responsePromise = client.contexts.update('id'); + const responsePromise = client.contexts.update('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -55,8 +55,8 @@ describe('resource contexts', () => { test('update: request options instead of params are passed correctly', async () => { // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect(client.contexts.update('id', { path: '/_stainless_unknown_path' })).rejects.toThrow( - Browserbase.NotFoundError, - ); + await expect( + client.contexts.update('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { path: '/_stainless_unknown_path' }), + ).rejects.toThrow(Browserbase.NotFoundError); }); }); diff --git a/tests/api-resources/extensions.test.ts b/tests/api-resources/extensions.test.ts index f839e39..3813a2e 100644 --- a/tests/api-resources/extensions.test.ts +++ b/tests/api-resources/extensions.test.ts @@ -29,7 +29,7 @@ describe('resource extensions', () => { }); test('retrieve', async () => { - const responsePromise = client.extensions.retrieve('id'); + const responsePromise = client.extensions.retrieve('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -41,13 +41,15 @@ describe('resource extensions', () => { test('retrieve: request options instead of params are passed correctly', async () => { // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect(client.extensions.retrieve('id', { path: '/_stainless_unknown_path' })).rejects.toThrow( - Browserbase.NotFoundError, - ); + await expect( + client.extensions.retrieve('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { + path: '/_stainless_unknown_path', + }), + ).rejects.toThrow(Browserbase.NotFoundError); }); test('delete', async () => { - const responsePromise = client.extensions.delete('id'); + const responsePromise = client.extensions.delete('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -59,8 +61,8 @@ describe('resource extensions', () => { test('delete: request options instead of params are passed correctly', async () => { // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect(client.extensions.delete('id', { path: '/_stainless_unknown_path' })).rejects.toThrow( - Browserbase.NotFoundError, - ); + await expect( + client.extensions.delete('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { path: '/_stainless_unknown_path' }), + ).rejects.toThrow(Browserbase.NotFoundError); }); }); diff --git a/tests/api-resources/projects.test.ts b/tests/api-resources/projects.test.ts index bd10699..44e8cf4 100644 --- a/tests/api-resources/projects.test.ts +++ b/tests/api-resources/projects.test.ts @@ -10,7 +10,7 @@ const client = new Browserbase({ describe('resource projects', () => { test('retrieve', async () => { - const responsePromise = client.projects.retrieve('id'); + const responsePromise = client.projects.retrieve('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -22,9 +22,9 @@ describe('resource projects', () => { test('retrieve: request options instead of params are passed correctly', async () => { // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect(client.projects.retrieve('id', { path: '/_stainless_unknown_path' })).rejects.toThrow( - Browserbase.NotFoundError, - ); + await expect( + client.projects.retrieve('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { path: '/_stainless_unknown_path' }), + ).rejects.toThrow(Browserbase.NotFoundError); }); test('list', async () => { @@ -46,7 +46,7 @@ describe('resource projects', () => { }); test('usage', async () => { - const responsePromise = client.projects.usage('id'); + const responsePromise = client.projects.usage('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -58,8 +58,8 @@ describe('resource projects', () => { test('usage: request options instead of params are passed correctly', async () => { // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect(client.projects.usage('id', { path: '/_stainless_unknown_path' })).rejects.toThrow( - Browserbase.NotFoundError, - ); + await expect( + client.projects.usage('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { path: '/_stainless_unknown_path' }), + ).rejects.toThrow(Browserbase.NotFoundError); }); }); diff --git a/tests/api-resources/sessions/downloads.test.ts b/tests/api-resources/sessions/downloads.test.ts index ca52b54..1092d7d 100644 --- a/tests/api-resources/sessions/downloads.test.ts +++ b/tests/api-resources/sessions/downloads.test.ts @@ -10,8 +10,10 @@ const client = new Browserbase({ describe('resource downloads', () => { test('list: request options instead of params are passed correctly', async () => { // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect(client.sessions.downloads.list('id', { path: '/_stainless_unknown_path' })).rejects.toThrow( - Browserbase.NotFoundError, - ); + await expect( + client.sessions.downloads.list('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { + path: '/_stainless_unknown_path', + }), + ).rejects.toThrow(Browserbase.NotFoundError); }); }); diff --git a/tests/api-resources/sessions/logs.test.ts b/tests/api-resources/sessions/logs.test.ts index bd5d738..ca22fe3 100644 --- a/tests/api-resources/sessions/logs.test.ts +++ b/tests/api-resources/sessions/logs.test.ts @@ -10,7 +10,7 @@ const client = new Browserbase({ describe('resource logs', () => { test('list', async () => { - const responsePromise = client.sessions.logs.list('id'); + const responsePromise = client.sessions.logs.list('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -22,8 +22,8 @@ describe('resource logs', () => { test('list: request options instead of params are passed correctly', async () => { // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect(client.sessions.logs.list('id', { path: '/_stainless_unknown_path' })).rejects.toThrow( - Browserbase.NotFoundError, - ); + await expect( + client.sessions.logs.list('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { path: '/_stainless_unknown_path' }), + ).rejects.toThrow(Browserbase.NotFoundError); }); }); diff --git a/tests/api-resources/sessions/recording.test.ts b/tests/api-resources/sessions/recording.test.ts index bdb7eb5..e9bd9cd 100644 --- a/tests/api-resources/sessions/recording.test.ts +++ b/tests/api-resources/sessions/recording.test.ts @@ -10,7 +10,7 @@ const client = new Browserbase({ describe('resource recording', () => { test('retrieve', async () => { - const responsePromise = client.sessions.recording.retrieve('id'); + const responsePromise = client.sessions.recording.retrieve('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -23,7 +23,9 @@ describe('resource recording', () => { test('retrieve: request options instead of params are passed correctly', async () => { // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error await expect( - client.sessions.recording.retrieve('id', { path: '/_stainless_unknown_path' }), + client.sessions.recording.retrieve('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { + path: '/_stainless_unknown_path', + }), ).rejects.toThrow(Browserbase.NotFoundError); }); }); diff --git a/tests/api-resources/sessions/sessions.test.ts b/tests/api-resources/sessions/sessions.test.ts index 63ffc71..999c92f 100644 --- a/tests/api-resources/sessions/sessions.test.ts +++ b/tests/api-resources/sessions/sessions.test.ts @@ -10,7 +10,7 @@ const client = new Browserbase({ describe('resource sessions', () => { test('create: only required params', async () => { - const responsePromise = client.sessions.create({ projectId: 'projectId' }); + const responsePromise = client.sessions.create({ projectId: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -22,14 +22,14 @@ describe('resource sessions', () => { test('create: required and optional params', async () => { const response = await client.sessions.create({ - projectId: 'projectId', + projectId: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', browserSettings: { advancedStealth: true, blockAds: true, captchaImageSelector: 'captchaImageSelector', captchaInputSelector: 'captchaInputSelector', - context: { id: 'id', persist: true }, - extensionId: 'extensionId', + context: { id: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', persist: true }, + extensionId: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', fingerprint: { browsers: ['chrome'], devices: ['desktop'], @@ -43,9 +43,15 @@ describe('resource sessions', () => { solveCaptchas: true, viewport: { height: 0, width: 0 }, }, - extensionId: 'extensionId', + extensionId: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', keepAlive: true, - proxies: true, + proxies: [ + { + type: 'browserbase', + domainPattern: 'domainPattern', + geolocation: { country: 'xx', city: 'city', state: 'xx' }, + }, + ], region: 'us-west-2', timeout: 60, userMetadata: { foo: 'bar' }, @@ -53,7 +59,7 @@ describe('resource sessions', () => { }); test('retrieve', async () => { - const responsePromise = client.sessions.retrieve('id'); + const responsePromise = client.sessions.retrieve('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -65,14 +71,14 @@ describe('resource sessions', () => { test('retrieve: request options instead of params are passed correctly', async () => { // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect(client.sessions.retrieve('id', { path: '/_stainless_unknown_path' })).rejects.toThrow( - Browserbase.NotFoundError, - ); + await expect( + client.sessions.retrieve('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { path: '/_stainless_unknown_path' }), + ).rejects.toThrow(Browserbase.NotFoundError); }); test('update: only required params', async () => { - const responsePromise = client.sessions.update('id', { - projectId: 'projectId', + const responsePromise = client.sessions.update('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { + projectId: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', status: 'REQUEST_RELEASE', }); const rawResponse = await responsePromise.asResponse(); @@ -85,8 +91,8 @@ describe('resource sessions', () => { }); test('update: required and optional params', async () => { - const response = await client.sessions.update('id', { - projectId: 'projectId', + const response = await client.sessions.update('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { + projectId: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', status: 'REQUEST_RELEASE', }); }); @@ -117,7 +123,7 @@ describe('resource sessions', () => { }); test('debug', async () => { - const responsePromise = client.sessions.debug('id'); + const responsePromise = client.sessions.debug('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -129,8 +135,8 @@ describe('resource sessions', () => { test('debug: request options instead of params are passed correctly', async () => { // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect(client.sessions.debug('id', { path: '/_stainless_unknown_path' })).rejects.toThrow( - Browserbase.NotFoundError, - ); + await expect( + client.sessions.debug('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { path: '/_stainless_unknown_path' }), + ).rejects.toThrow(Browserbase.NotFoundError); }); }); diff --git a/tests/api-resources/sessions/uploads.test.ts b/tests/api-resources/sessions/uploads.test.ts index c5872c3..1900d34 100644 --- a/tests/api-resources/sessions/uploads.test.ts +++ b/tests/api-resources/sessions/uploads.test.ts @@ -10,7 +10,7 @@ const client = new Browserbase({ describe('resource uploads', () => { test('create: only required params', async () => { - const responsePromise = client.sessions.uploads.create('id', { + const responsePromise = client.sessions.uploads.create('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { file: await toFile(Buffer.from('# my file contents'), 'README.md'), }); const rawResponse = await responsePromise.asResponse(); @@ -23,7 +23,7 @@ describe('resource uploads', () => { }); test('create: required and optional params', async () => { - const response = await client.sessions.uploads.create('id', { + const response = await client.sessions.uploads.create('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { file: await toFile(Buffer.from('# my file contents'), 'README.md'), }); }); diff --git a/tests/index.test.ts b/tests/index.test.ts index 9d1c3b2..8a0df9f 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -185,6 +185,28 @@ describe('instantiate client', () => { const client = new Browserbase({ apiKey: 'My API Key' }); expect(client.baseURL).toEqual('https://api.browserbase.com'); }); + + test('in request options', () => { + const client = new Browserbase({ apiKey: 'My API Key' }); + expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual( + 'http://localhost:5000/option/foo', + ); + }); + + test('in request options overridden by client options', () => { + const client = new Browserbase({ apiKey: 'My API Key', baseURL: 'http://localhost:5000/client' }); + expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual( + 'http://localhost:5000/client/foo', + ); + }); + + test('in request options overridden by env variable', () => { + process.env['BROWSERBASE_BASE_URL'] = 'http://localhost:5000/env'; + const client = new Browserbase({ apiKey: 'My API Key' }); + expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual( + 'http://localhost:5000/env/foo', + ); + }); }); test('maxRetries option is correctly set', () => {