Skip to content
This repository was archived by the owner on Dec 20, 2025. It is now read-only.
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
47 changes: 36 additions & 11 deletions packages/google-sr/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,47 +77,72 @@ export interface SearchOptions<
N extends boolean = false,
> {
/**
* Search query
* The search query string to send to Google.
*/
query: string;

/**
* Control the type of results returned (can have a significant performance impact)
* Array of result parsers that determine which types of results to extract.
*
* Each parser processes the HTML response and extracts specific result types.
* Using fewer parsers can improve performance.
*
* @default [OrganicResult] - Only organic results are parsed if not specified
*/
parsers?: R[];

/**
* When true, excludes results that have undefined or empty properties.
* Whether to exclude results with missing or undefined properties.
* @default false - Partial results are included.
*/
noPartialResults?: N;

/**
* Custom request configuration to be sent with the request
* Custom HTTP request configuration for the search request.
*
* Accepts all standard Fetch API options (headers, method, signal, etc.)
* plus additional google-sr specific properties.
*
* @example
* ```ts
* requestConfig: {
* signal: abortController.signal,
* queryParams: { tbm: 'nws' }, // this is provided by google-sr
* }
* ```
*/
requestConfig?: RequestOptions;
}

/**
* Search options for multiple pages search
* Configuration options for multi-page search.
*/
export interface SearchOptionsWithPages<
R extends ResultParser = ResultParser,
N extends boolean = false,
> extends SearchOptions<R, N> {
/**
* Total number of pages to search or an array of specific pages to search
* Specifies which pages to search.
*
* google search uses cursor-based pagination.
* - **Number**: Total pages to search starting from page 1
* - **Array**: Specific page offsets to search (0 = page 1, 10 = page 2, etc.)
*
* Specific page numbers are incremented by 10 starting from 0 (page 1)
* Google uses cursor-based pagination with increments of 10.
*
* If total number of pages is provided, cursor will be created according to: start = page * 10
* @example
* ```ts
* pages: 3 // Searches pages 1, 2, 3 (offsets: 0, 10, 20)
* pages: [0, 20] // Searches pages 1 and 3 (offsets: 0, 20)
* ```
*/
pages: number | number[];
/**
* Delay between each request in milliseconds. helps to avoid rate limiting issues.
* Delay between requests in milliseconds.
*
* Helps prevent rate limiting by spacing out requests.
* Set to 0 to disable delays (not recommended for production).
*
* Default is 1000 ms (1 second). set to 0 to disable delay.
* @default 1000 - 1 second delay between requests
*/
delay?: number;
}
Expand Down
7 changes: 6 additions & 1 deletion packages/google-sr/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,9 @@ export * from "./constants.js";
export * from "./results/index.js";
export * from "./search.js";

export type { SearchResultTypeFromParser } from "./utils.js";
// export some of the utility functions for ease of use
export type {
ParserResultType,
PartialExceptType,
SearchResultTypeFromParser,
} from "./utils.js";
17 changes: 16 additions & 1 deletion packages/google-sr/src/results/conversion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,22 @@ export interface UnitConversionResultNode extends SearchResultNodeLike {

/**
* Parses unit conversion search results.
* @returns Array of UnitConversionResultNode
*
* @example
* ```ts
* import { UnitConversionResult, search } from 'google-sr';
*
* const results = await search({
* query: '100 USD to EUR',
* parsers: [UnitConversionResult],
* });
* ```
*
* @param $ - The CheerioAPI instance
* @param noPartialResults - Whether to exclude results with missing properties
* @returns
* - If noPartialResults is true: {@link UnitConversionResultNode} object or null
* - If noPartialResults is false: {@link PartialExceptType}<{@link UnitConversionResultNode}> object or null
*/
export const UnitConversionResult: ResultParser<UnitConversionResultNode> = (
$,
Expand Down
17 changes: 16 additions & 1 deletion packages/google-sr/src/results/dictionary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,22 @@ const parseDefinitionBlock = (

/**
* Parses dictionary search results.
* @returns Array of DictionaryResultNode
*
* @example
* ```ts
* import { DictionaryResult, search } from 'google-sr';
*
* const results = await search({
* query: 'define serendipity',
* parsers: [DictionaryResult],
* });
* ```
*
* @param $ - The CheerioAPI instance
* @param noPartialResults - Whether to exclude results with missing properties
* @returns
* - If noPartialResults is true: {@link DictionaryResultNode} object or null
* - If noPartialResults is false: {@link PartialExceptType}<{@link DictionaryResultNode}> object or null
*/
export const DictionaryResult: ResultParser<DictionaryResultNode> = (
$,
Expand Down
20 changes: 17 additions & 3 deletions packages/google-sr/src/results/knowledge-panel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,23 @@ export interface KnowledgePanelResultNode extends SearchResultNodeLike {

/**
* Parses knowledge panel search results.
* @param $
* @param noPartialResults
* @returns KnowledgePanelResultNode
* Knowledge panels appear for well-known entities like people, places, and organizations.
*
* @example
* ```ts
* import { KnowledgePanelResult, search } from 'google-sr';
*
* const results = await search({
* query: 'Albert Einstein',
* parsers: [KnowledgePanelResult],
* });
* ```
*
* @param $ - The CheerioAPI instance
* @param noPartialResults - Whether to exclude results with missing properties
* @returns
* - If noPartialResults is true: {@link KnowledgePanelResultNode} object or null
* - If noPartialResults is false: {@link PartialExceptType}<{@link KnowledgePanelResultNode}> object or null
*/
export const KnowledgePanelResult: ResultParser<KnowledgePanelResultNode> = (
$,
Expand Down
9 changes: 7 additions & 2 deletions packages/google-sr/src/results/news.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export interface NewsResultNode extends SearchResultNodeLike {
/**
* Parses results from the dedicated News tab in Google Search.
*
* To use this selector, set the `tbm` query parameter to `'nws'` in the request configuration.
* To use this parser, set the `tbm` query parameter to `'nws'` in the request configuration.
*
* **NOTE: This parser is not compatible with the other parsers and vice versa.**
*
Expand All @@ -42,7 +42,12 @@ export interface NewsResultNode extends SearchResultNodeLike {
* });
* ```
*
* @returns Array of {@link NewsResultNode} objects
* @param $ - The CheerioAPI instance
* @param noPartialResults - Whether to exclude results with missing properties
* @returns
* - If noPartialResults is true: Array of {@link NewsResultNode} objects
* - If noPartialResults is false: Array of {@link PartialExceptType}<{@link NewsResultNode}> objects
* - If no results are found: returns an empty array
*/
export const NewsResult: ResultParser<NewsResultNode> = (
$,
Expand Down
8 changes: 6 additions & 2 deletions packages/google-sr/src/results/organic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,19 @@ export interface OrganicResultNode extends SearchResultNodeLike {
* @example
* ```ts
* import { OrganicResult, search } from 'google-sr';
*
* const results = await search({
* query: 'google-sr npm package',
* parsers: [OrganicResult],
* });
* ```
*
* @param $ - The CheerioAPI instance
* @param noPartialResults - Whether to exclude results with missing properties
* @returns
* - Array of {@link OrganicResultNode} objects
* - If noPartialResult is true, Array of {@link PartialExceptType}<{@link OrganicResultNode}> objects
* - If noPartialResults is true: Array of {@link OrganicResultNode} objects
* - If noPartialResults is false: Array of {@link PartialExceptType}<{@link OrganicResultNode}> objects
* - If no results are found: returns an empty array
*/
export const OrganicResult: ResultParser<OrganicResultNode> = (
$,
Expand Down
9 changes: 6 additions & 3 deletions packages/google-sr/src/results/related-searches.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,24 @@ export interface RelatedSearchesResultNode extends SearchResultNodeLike {
/**
* Parses related search queries that appear at the bottom of Google search results.
* This parser extracts the "Related searches" or similar related query suggestions
* that Google displays to help users refine their search.
* that Google displays to help users find similar or relevant topics.
*
* @example
* ```ts
* import { RelatedSearchesResult, search } from 'google-sr';
*
* const results = await search({
* query: 'nodejs frameworks',
* parsers: [RelatedSearchesResult],
* });
* // results[0].queries might contain: ["express.js", "react.js", ...]
* ```
*
* @param $ - The CheerioAPI instance
* @param noPartialResults - Whether to exclude results with missing properties
* @returns
* - If noPartialResults is true, {@link RelatedSearchesResultNode} object
* - If noPartialResults is false, {@link PartialExceptType}<{@link RelatedSearchesResultNode}> object
* - If noPartialResults is true: {@link RelatedSearchesResultNode} object or null
* - If noPartialResults is false: {@link PartialExceptType}<{@link RelatedSearchesResultNode}> object or null
*/
export const RelatedSearchesResult: ResultParser<RelatedSearchesResultNode> = (
$,
Expand Down
17 changes: 16 additions & 1 deletion packages/google-sr/src/results/time.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,22 @@ export interface TimeResultNode extends SearchResultNodeLike {

/**
* Parses time search results.
* @returns Array of TimeResultNode
*
* @example
* ```ts
* import { TimeResult, search } from 'google-sr';
*
* const results = await search({
* query: 'time in new york',
* parsers: [TimeResult],
* });
* ```
*
* @param $ - The CheerioAPI instance
* @param noPartialResults - Whether to exclude results with missing properties
* @returns
* - If noPartialResults is true: {@link TimeResultNode} object or null
* - If noPartialResults is false: {@link PartialExceptType}<{@link TimeResultNode}> object or null
*/
export const TimeResult: ResultParser<TimeResultNode> = (
$,
Expand Down
17 changes: 16 additions & 1 deletion packages/google-sr/src/results/translate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,22 @@ export interface TranslateResultNode extends SearchResultNodeLike {

/**
* Parses translation search results.
* @returns Array of TranslateSearchResultNodes
*
* @example
* ```ts
* import { TranslateResult, search } from 'google-sr';
*
* const results = await search({
* query: 'translate hello to spanish',
* parsers: [TranslateResult],
* });
* ```
*
* @param $ - The CheerioAPI instance
* @param noPartialResults - Whether to exclude results with missing properties
* @returns
* - If noPartialResults is true: {@link TranslateResultNode} object or null
* - If noPartialResults is false: {@link PartialExceptType}<{@link TranslateResultNode}> object or null
*/
export const TranslateResult: ResultParser<TranslateResultNode> = (
$,
Expand Down
53 changes: 53 additions & 0 deletions packages/google-sr/src/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,28 @@ import {
safeGetFetch,
} from "./utils.js";

/**
* Performs a Google search and returns parsed results from a single page.
*
* This is the main search function for single-page searches. It accepts various parsers
* to extract different types of results (organic results, news, translations, etc.).
*
* @example
* ```ts
* import { search, OrganicResult } from 'google-sr';
*
* const results = await search({
* query: 'nodejs tutorial',
* // Configure the parsers you want
* parsers: [OrganicResult],
* noPartialResults: true
* });
* ```
*
* @param searchOptions - Configuration options for the search
* @returns Promise that resolves to an array of parsed search results
* @throws {TypeError} When searchOptions is not provided or is invalid
*/
export async function search<R extends ResultParser, N extends boolean = false>(
searchOptions: SearchOptions<R, N>,
): Promise<SearchResultTypeFromParser<R, N>[]> {
Expand Down Expand Up @@ -41,6 +63,37 @@ export async function search<R extends ResultParser, N extends boolean = false>(
return searchResults;
}

/**
* Performs a Google search across multiple pages and returns parsed results.
*
* This function efficiently searches multiple pages by reusing the same parsers
* and request configuration. Results are returned as a 2D array where each
* sub-array contains results from one page.
*
* @example
* ```ts
* import { searchWithPages, OrganicResult } from 'google-sr';
*
* // Search first 3 pages
* const results = await searchWithPages({
* query: 'machine learning',
* parsers: [OrganicResult],
* pages: 3, // Will search pages 0, 10, 20
* delay: 1000 // 1 second delay between requests
* });
*
* // Search specific pages
* const specificResults = await searchWithPages({
* query: 'react hooks',
* parsers: [OrganicResult],
* pages: [0, 20, 40], // Search pages 1, 3, and 5
* });
* ```
*
* @param options - Configuration options for the multi-page search
* @returns Promise that resolves to a 2D array where each sub-array contains results from one page
* @throws {TypeError} When options is not provided or pages parameter is invalid
*/
export async function searchWithPages<
R extends ResultParser = typeof OrganicResult,
N extends boolean = false,
Expand Down
Loading