|
6 | 6 | APIConnectionTimeoutError, |
7 | 7 | APIUserAbortError, |
8 | 8 | } from './error'; |
| 9 | +import { stringifyQuery } from './internal/utils/query'; |
9 | 10 | import { |
10 | 11 | kind as shimsKind, |
11 | 12 | type Readable, |
@@ -523,32 +524,20 @@ export abstract class APIClient { |
523 | 524 | : new URL(baseURL + (baseURL.endsWith('/') && path.startsWith('/') ? path.slice(1) : path)); |
524 | 525 |
|
525 | 526 | const defaultQuery = this.defaultQuery(); |
526 | | - if (!isEmptyObj(defaultQuery)) { |
527 | | - query = { ...defaultQuery, ...query } as Req; |
| 527 | + const pathQuery = Object.fromEntries(url.searchParams); |
| 528 | + if (!isEmptyObj(defaultQuery) || !isEmptyObj(pathQuery)) { |
| 529 | + query = { ...pathQuery, ...defaultQuery, ...query } as Req; |
528 | 530 | } |
529 | 531 |
|
530 | 532 | if (typeof query === 'object' && query && !Array.isArray(query)) { |
531 | | - url.search = this.stringifyQuery(query as Record<string, unknown>); |
| 533 | + url.search = this.stringifyQuery(query); |
532 | 534 | } |
533 | 535 |
|
534 | 536 | return url.toString(); |
535 | 537 | } |
536 | 538 |
|
537 | | - protected stringifyQuery(query: Record<string, unknown>): string { |
538 | | - return Object.entries(query) |
539 | | - .filter(([_, value]) => typeof value !== 'undefined') |
540 | | - .map(([key, value]) => { |
541 | | - if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { |
542 | | - return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`; |
543 | | - } |
544 | | - if (value === null) { |
545 | | - return `${encodeURIComponent(key)}=`; |
546 | | - } |
547 | | - throw new BrowserbaseError( |
548 | | - `Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`, |
549 | | - ); |
550 | | - }) |
551 | | - .join('&'); |
| 539 | + protected stringifyQuery(query: object | Record<string, unknown>): string { |
| 540 | + return stringifyQuery(query); |
552 | 541 | } |
553 | 542 |
|
554 | 543 | async fetchWithTimeout( |
@@ -630,9 +619,9 @@ export abstract class APIClient { |
630 | 619 | } |
631 | 620 | } |
632 | 621 |
|
633 | | - // If the API asks us to wait a certain amount of time (and it's a reasonable amount), |
634 | | - // just do what it says, but otherwise calculate a default |
635 | | - if (!(timeoutMillis && 0 <= timeoutMillis && timeoutMillis < 60 * 1000)) { |
| 622 | + // If the API asks us to wait a certain amount of time, do what it says. |
| 623 | + // Otherwise calculate a default. |
| 624 | + if (timeoutMillis === undefined) { |
636 | 625 | const maxRetries = options.maxRetries ?? this.maxRetries; |
637 | 626 | timeoutMillis = this.calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries); |
638 | 627 | } |
|
0 commit comments