{"version":3,"file":"serpapi.cjs","names":["BaseDocumentLoader","Document"],"sources":["../../../src/document_loaders/web/serpapi.ts"],"sourcesContent":["import { Document } from \"@langchain/core/documents\";\nimport { getEnvironmentVariable } from \"@langchain/core/utils/env\";\nimport { BaseDocumentLoader } from \"@langchain/core/document_loaders/base\";\n\n/**\n * Interface representing the parameters for the SerpAPI loader. It\n * includes properties such as the search query and the API key.\n */\ninterface SerpAPIParameters {\n  /**\n   * Search Query\n   */\n  q: string;\n  apiKey?: string;\n}\n\n/**\n * Class representing a document loader for loading search results from\n * the SerpAPI. It extends the BaseDocumentLoader class.\n * @example\n * ```typescript\n * const loader = new SerpAPILoader({ q: \"{query}\", apiKey: \"{apiKey}\" });\n * const docs = await loader.load();\n * ```\n */\nexport class SerpAPILoader extends BaseDocumentLoader {\n  private apiKey: string;\n\n  private searchQuery: string;\n\n  constructor(params: SerpAPIParameters) {\n    super();\n    const { apiKey = getEnvironmentVariable(\"SERPAPI_API_KEY\"), q } = params;\n    if (!apiKey) {\n      throw new Error(\n        \"SerpAPI API key not set. You can set it as SERPAPI_API_KEY in your .env file, or pass it to SerpAPI.\"\n      );\n    }\n\n    this.apiKey = apiKey;\n    this.searchQuery = q;\n  }\n\n  /**\n   * Builds the URL for the SerpAPI search request.\n   * @returns The URL for the search request.\n   */\n  public buildUrl(): string {\n    const params = new URLSearchParams();\n    params.append(\"api_key\", this.apiKey);\n    params.append(\"q\", this.searchQuery);\n    return `https://serpapi.com/search?${params.toString()}`;\n  }\n\n  /**\n   * Extracts documents from the provided output.\n   * @param output - The output to extract documents from.\n   * @param responseType - The type of the response to extract documents from.\n   * @returns An array of Documents.\n   */\n  private extractDocuments(output: unknown, responseType: string): Document[] {\n    const documents: Document[] = [];\n    const results = Array.isArray(output) ? output : [output];\n    for (const result of results) {\n      const pageContent = JSON.stringify(result);\n      const metadata = {\n        source: \"SerpAPI\",\n        responseType,\n      };\n      documents.push(new Document({ pageContent, metadata }));\n    }\n    return documents;\n  }\n\n  /**\n   * Processes the response data from the SerpAPI search request and converts it into an array of Documents.\n   * @param data - The response data from the SerpAPI search request.\n   * @returns An array of Documents.\n   */\n  public processResponseData(data: Record<string, unknown>): Document[] {\n    const documents: Document[] = [];\n    const responseTypes = [\n      \"answer_box\",\n      \"sports_results\",\n      \"shopping_results\",\n      \"knowledge_graph\",\n      \"organic_results\",\n    ];\n    for (const responseType of responseTypes) {\n      if (responseType in data) {\n        documents.push(\n          ...this.extractDocuments(data[responseType], responseType)\n        );\n      }\n    }\n    return documents;\n  }\n\n  /**\n   * Fetches the data from the provided URL and returns it as a JSON object.\n   * If an error occurs during the fetch operation, an exception is thrown with the error message.\n   * @param url - The URL to fetch data from.\n   * @returns A promise that resolves to the fetched data as a JSON object.\n   * @throws An error if the fetch operation fails.\n   */\n  private async fetchData(url: string): Promise<Record<string, unknown>> {\n    const response = await fetch(url);\n    const data = await response.json();\n\n    if (data.error) {\n      throw new Error(\n        `Failed to load search results from SerpAPI due to: ${data.error}`\n      );\n    }\n\n    return data;\n  }\n\n  /**\n   * Loads the search results from the SerpAPI.\n   * @returns An array of Documents representing the search results.\n   * @throws An error if the search results could not be loaded.\n   */\n  public async load(): Promise<Document[]> {\n    const url = this.buildUrl();\n\n    const data = await this.fetchData(url);\n    try {\n      return this.processResponseData(data);\n    } catch (error) {\n      console.error(error);\n      throw new Error(\n        `Failed to process search results from SerpAPI: ${error}`\n      );\n    }\n  }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAyBA,IAAa,gBAAb,cAAmCA,sCAAAA,mBAAmB;CACpD;CAEA;CAEA,YAAY,QAA2B;AACrC,SAAO;EACP,MAAM,EAAE,UAAA,GAAA,0BAAA,wBAAgC,kBAAkB,EAAE,MAAM;AAClE,MAAI,CAAC,OACH,OAAM,IAAI,MACR,uGACD;AAGH,OAAK,SAAS;AACd,OAAK,cAAc;;;;;;CAOrB,WAA0B;EACxB,MAAM,SAAS,IAAI,iBAAiB;AACpC,SAAO,OAAO,WAAW,KAAK,OAAO;AACrC,SAAO,OAAO,KAAK,KAAK,YAAY;AACpC,SAAO,8BAA8B,OAAO,UAAU;;;;;;;;CASxD,iBAAyB,QAAiB,cAAkC;EAC1E,MAAM,YAAwB,EAAE;EAChC,MAAM,UAAU,MAAM,QAAQ,OAAO,GAAG,SAAS,CAAC,OAAO;AACzD,OAAK,MAAM,UAAU,SAAS;GAC5B,MAAM,cAAc,KAAK,UAAU,OAAO;GAC1C,MAAM,WAAW;IACf,QAAQ;IACR;IACD;AACD,aAAU,KAAK,IAAIC,0BAAAA,SAAS;IAAE;IAAa;IAAU,CAAC,CAAC;;AAEzD,SAAO;;;;;;;CAQT,oBAA2B,MAA2C;EACpE,MAAM,YAAwB,EAAE;AAQhC,OAAK,MAAM,gBAPW;GACpB;GACA;GACA;GACA;GACA;GACD,CAEC,KAAI,gBAAgB,KAClB,WAAU,KACR,GAAG,KAAK,iBAAiB,KAAK,eAAe,aAAa,CAC3D;AAGL,SAAO;;;;;;;;;CAUT,MAAc,UAAU,KAA+C;EAErE,MAAM,OAAO,OADI,MAAM,MAAM,IAAI,EACL,MAAM;AAElC,MAAI,KAAK,MACP,OAAM,IAAI,MACR,sDAAsD,KAAK,QAC5D;AAGH,SAAO;;;;;;;CAQT,MAAa,OAA4B;EACvC,MAAM,MAAM,KAAK,UAAU;EAE3B,MAAM,OAAO,MAAM,KAAK,UAAU,IAAI;AACtC,MAAI;AACF,UAAO,KAAK,oBAAoB,KAAK;WAC9B,OAAO;AACd,WAAQ,MAAM,MAAM;AACpB,SAAM,IAAI,MACR,kDAAkD,QACnD"}