Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions packages/brave/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const braveSDK = createBraveSDK({
const braveSDK = createBraveSDK(); // Uses BRAVE_API_KEY from environment
```

## Rate Limits ( DO NOT USE PROMISE.A;l )
## Rate Limits ( DO NOT USE PROMISE.All )

- Free Plan: 1 request per second
- Pro Plan: 20 requests per second
Expand All @@ -43,11 +43,10 @@ const results = await Promise.all([
]);

// ✅ Do this instead
const results = [];
for (const query of ['query1', 'query2']) {
results.push(await braveSDK.webSearch({ q: query }));
await new Promise(resolve => setTimeout(resolve, 1000)); // 1 second delay
}
const results = await braveSdk.batchWebSearch([
{ q: 'query1' },
{ q: 'query2' },
]);
```

## API Reference
Expand Down
27 changes: 27 additions & 0 deletions packages/brave/docs/imageSearch.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,33 @@ const processResults = async () => {
console.error('Error performing image search:', error);
}
};

// Batch image search example
const batchImageSearchExample = async () => {
try {
// Define multiple image search queries
const searchQueries = [
{ q: 'cats', count: 5, safesearch: 'moderate' },
{ q: 'dogs', count: 5, safesearch: 'moderate' },
{ q: 'birds', count: 5, safesearch: 'moderate' },
];

// Process batch search with progress tracking
const results = await braveSDK.batchImageSearch(searchQueries);

// Process results for each query
results.forEach((response, index) => {
console.log(`\nResults for query "${searchQueries[index].q}":`);
const images = response.mixed.main;

images.forEach(image => {
console.log(`- ${image.title} (${image.source})`);
});
});
} catch (error) {
console.error('Error performing batch image search:', error);
}
};
```

## Notes
Expand Down
31 changes: 31 additions & 0 deletions packages/brave/docs/newsSearch.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,4 +124,35 @@ const articlesBySource = results.results.reduce(
},
{} as Record<string, typeof results.results>,
);

// Example: Batch news search
const batchResults = await braveSDK.batchNewsSearch(
[
{ q: 'technology news', freshness: 'pd' },
{ q: 'sports news', country: 'US', count: 10 },
{ q: 'business news', freshness: 'pw' },
],
{
delay: 1000, // 1 second delay between requests
onProgress: (completed, total) => {
console.log(`Completed ${completed} of ${total} requests`);
},
},
);

// Process batch results
batchResults.forEach((result, index) => {
if ('error' in result) {
console.error(`Error in request ${index + 1}:`, result.error);
return;
}

console.log(`\nResults for search ${index + 1}:`);
result.results.forEach((article, articleIndex) => {
console.log(`\nArticle ${articleIndex + 1}:`);
console.log('Title:', article.title);
console.log('Source:', article.meta_url?.source);
console.log('Age:', article.age);
});
});
```
34 changes: 34 additions & 0 deletions packages/brave/docs/videoSearch.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,4 +143,38 @@ const videosByCreator = results.results.reduce(
},
{} as Record<string, typeof results.results>,
);

// Example: Batch video search
const batchResults = await braveSDK.batchVideoSearch(
[
{ q: 'cute puppies', count: 5 },
{ q: 'funny cats', count: 5 },
{ q: 'baby animals', count: 5 },
],
{
delay: 1000, // 1 second delay between requests
onProgress: (completed, total) => {
console.log(`Completed ${completed} of ${total} searches`);
},
},
);

// Process batch results
batchResults.forEach((result, index) => {
if ('error' in result) {
console.error(`Search ${index + 1} failed:`, result.error);
return;
}

console.log(`\nResults for search ${index + 1}:`);
result.results.forEach((video, videoIndex) => {
console.log(`\nVideo ${videoIndex + 1}:`);
console.log('Title:', video.title);
console.log('URL:', video.url);
if (video.video) {
console.log('Duration:', video.video.duration);
console.log('Views:', video.video.views);
}
});
});
```
29 changes: 29 additions & 0 deletions packages/brave/docs/webSearch.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,33 @@ if (results.type === 'web') {
console.log('FAQ Results:', results.faq.results);
}
}

// Batch web search example
const batchResults = await braveSDK.batchWebSearch([
{ q: 'TypeScript' },
{ q: 'JavaScript', count: 10 },
{ q: 'Python', freshness: 'pw' },
]);

// Process batch results
batchResults.forEach((result, index) => {
if (result.type === 'web' && result.search) {
console.log(`Batch ${index + 1} Results:`);
result.search.results.forEach((searchResult, resultIndex) => {
console.log(` Result ${resultIndex + 1}:`, searchResult.title);
console.log(' URL:', searchResult.url);
});
}
});

// Batch search with progress tracking
const batchResultsWithProgress = await braveSDK.batchWebSearch(
[{ q: 'React' }, { q: 'Vue' }, { q: 'Angular' }],
{
delay: 2000, // 2 second delay between requests
onProgress: (completed, total) => {
console.log(`Completed ${completed} of ${total} searches`);
},
},
);
```
138 changes: 138 additions & 0 deletions packages/brave/src/BraveSdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,33 @@ export type MiddlewareFunction = (request: {
useLocalSearchHeaders: boolean;
}>;

export interface BatchRequestOptions {
delay?: number; // Delay between requests in milliseconds
onProgress?: (completed: number, total: number) => void; // Progress callback
}

export type BatchRequest = {
type:
| 'web'
| 'image'
| 'video'
| 'news'
| 'suggest'
| 'spellcheck'
| 'summarizer'
| 'localPoi'
| 'localDescriptions';
params:
| WebSearchParams
| ImageSearchParams
| VideoSearchParams
| NewsSearchParams
| SuggestSearchParams
| SpellcheckSearchParams
| SummarizerSearchParams
| LocalSearchParams;
};

class BraveSDK {
private apiKey: string;
private baseUrl = 'https://api.search.brave.com/res/v1';
Expand Down Expand Up @@ -137,6 +164,12 @@ class BraveSDK {
return this.request<WebSearchApiResponse>('/web/search', params);
}

async batchWebSearch(
params: WebSearchParams[],
): Promise<WebSearchApiResponse[]> {
return this.batchProcess(params.map(p => ({ type: 'web', params: p })));
}

async localPoiSearch(
params: LocalSearchParams,
): Promise<LocalPoiSearchApiResponse> {
Expand Down Expand Up @@ -168,16 +201,34 @@ class BraveSDK {
return this.request<ImageSearchApiResponse>('/images/search', params);
}

async batchImageSearch(
params: ImageSearchParams[],
): Promise<ImageSearchApiResponse[]> {
return this.batchProcess(params.map(p => ({ type: 'image', params: p })));
}

async videoSearch(
params: VideoSearchParams,
): Promise<VideoSearchApiResponse> {
return this.request<VideoSearchApiResponse>('/videos/search', params);
}

async batchVideoSearch(
params: VideoSearchParams[],
): Promise<VideoSearchApiResponse[]> {
return this.batchProcess(params.map(p => ({ type: 'video', params: p })));
}

async newsSearch(params: NewsSearchParams): Promise<NewsSearchApiResponse> {
return this.request<NewsSearchApiResponse>('/news/search', params);
}

async batchNewsSearch(
params: NewsSearchParams[],
): Promise<NewsSearchApiResponse[]> {
return this.batchProcess(params.map(p => ({ type: 'news', params: p })));
}

async suggestSearch(
params: SuggestSearchParams,
): Promise<SuggestSearchApiResponse> {
Expand All @@ -192,6 +243,93 @@ class BraveSDK {
params,
);
}

/**
* Process multiple requests sequentially with a configurable delay
* @param requests Array of requests to process
* @param options Configuration options for batch processing
* @returns Array of responses in the same order as requests
*/
async batchProcess<T extends any[]>(
requests: BatchRequest[],
options: BatchRequestOptions = {},
): Promise<T> {
const { delay = 1000, onProgress } = options;
const results: any[] = [];
const total = requests.length;

for (let i = 0; i < total; i++) {
const request = requests[i];
let response: any;

try {
switch (request.type) {
case 'web':
response = await this.webSearch(request.params as WebSearchParams);
break;
case 'image':
response = await this.imageSearch(
request.params as ImageSearchParams,
);
break;
case 'video':
response = await this.videoSearch(
request.params as VideoSearchParams,
);
break;
case 'news':
response = await this.newsSearch(
request.params as NewsSearchParams,
);
break;
case 'suggest':
response = await this.suggestSearch(
request.params as SuggestSearchParams,
);
break;
case 'spellcheck':
response = await this.spellcheckSearch(
request.params as SpellcheckSearchParams,
);
break;
case 'summarizer':
response = await this.summarizerSearch(
request.params as SummarizerSearchParams,
);
break;
case 'localPoi':
response = await this.localPoiSearch(
request.params as LocalSearchParams,
);
break;
case 'localDescriptions':
response = await this.localDescriptionsSearch(
request.params as LocalSearchParams,
);
break;
default:
throw new Error(`Unknown request type: ${request.type}`);
}

results.push(response);
} catch (error) {
results.push({
error: error instanceof Error ? error.message : 'Unknown error',
});
}

if (onProgress) {
onProgress(i + 1, total);
}

// Add delay between requests, except for the last one
if (i < total - 1) {
await new Promise(resolve => setTimeout(resolve, delay));
}
}

return results as T;
}
}

export function createBraveSDK(options?: BraveSDKOptions): BraveSDK {
Expand Down
Loading