{"version":3,"file":"airtable.cjs","names":["BaseDocumentLoader","AsyncCaller","documents: Document[]","offset: string | undefined","record: AirtableRecord","offset?: string","body: Record<string, any>","metadata: Record<string, any>","Document"],"sources":["../../../src/document_loaders/web/airtable.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { BaseDocumentLoader } from \"@langchain/core/document_loaders/base\";\nimport { Document } from \"@langchain/core/documents\";\nimport { getEnvironmentVariable } from \"@langchain/core/utils/env\";\nimport { AsyncCaller } from \"@langchain/core/utils/async_caller\";\n\nexport interface AirtableRequestParams {\n  view?: string;\n  maxRecords?: number;\n  filterByFormula?: string;\n  fields?: string[];\n}\n\nexport interface AirtableLoaderOptions {\n  tableId: string;\n  baseId: string;\n  kwargs?: AirtableRequestParams;\n}\n\ninterface AirtableRecord {\n  id: string;\n  fields: Record<string, any>;\n  createdTime: string;\n}\n\ninterface AirtableResponse {\n  records: AirtableRecord[];\n  offset?: string;\n}\n\nexport class AirtableLoader extends BaseDocumentLoader {\n  private readonly apiToken: string;\n\n  private readonly tableId: string;\n\n  private readonly baseId: string;\n\n  private readonly kwargs: AirtableRequestParams;\n\n  private static readonly BASE_URL = \"https://api.airtable.com/v0\";\n\n  private asyncCaller: AsyncCaller;\n\n  /**\n   * Initializes the AirtableLoader with configuration options.\n   * Retrieves the API token from environment variables and validates it.\n   *\n   * @param tableId - ID of the Airtable table.\n   * @param baseId - ID of the Airtable base.\n   * @param kwargs - Additional query parameters for Airtable requests.\n   * @param config - Loader configuration for retry options.\n   */\n  constructor({ tableId, baseId, kwargs = {} }: AirtableLoaderOptions) {\n    super();\n    this.apiToken = getEnvironmentVariable(\"AIRTABLE_API_TOKEN\") || \"\";\n    this.tableId = tableId;\n    this.baseId = baseId;\n    this.kwargs = kwargs;\n\n    if (!this.apiToken) {\n      throw new Error(\n        \"Missing Airtable API token. Please set AIRTABLE_API_TOKEN environment variable.\"\n      );\n    }\n\n    this.asyncCaller = new AsyncCaller({ maxRetries: 3, maxConcurrency: 5 });\n  }\n\n  /**\n   * Loads documents from Airtable, handling pagination and retries.\n   *\n   * @returns A promise that resolves to an array of Document objects.\n   */\n  public async load(): Promise<Document[]> {\n    const documents: Document[] = [];\n    let offset: string | undefined;\n\n    try {\n      do {\n        const body = this.constructRequestBody(offset);\n        const data = await this.asyncCaller.call(() => this.fetchRecords(body));\n        data.records.forEach((record: AirtableRecord) =>\n          documents.push(this.createDocument(record))\n        );\n        offset = data.offset;\n      } while (offset);\n    } catch (error) {\n      console.error(\"Error loading Airtable records:\", error);\n      throw new Error(\"Failed to load Airtable records\");\n    }\n\n    return documents;\n  }\n\n  /**\n   * Asynchronous generator function for lazily loading documents from Airtable.\n   * This method yields each document individually, enabling memory-efficient\n   * handling of large datasets by fetching records in pages.\n   *\n   * @returns An asynchronous generator yielding Document objects one by one.\n   */\n  public async *loadLazy(): AsyncGenerator<Document> {\n    let offset: string | undefined;\n    try {\n      do {\n        const body = this.constructRequestBody(offset);\n        const data = await this.asyncCaller.call(() => this.fetchRecords(body));\n\n        for (const record of data.records) {\n          yield this.createDocument(record);\n        }\n\n        offset = data.offset;\n      } while (offset);\n    } catch (error) {\n      console.error(\"Error loading Airtable records lazily:\", error);\n      throw new Error(\"Failed to load Airtable records lazily\");\n    }\n  }\n\n  /**\n   * Constructs the request body for an API call.\n   *\n   * @param offset - An optional string representing the offset for pagination.\n   * @returns A record containing the combined properties of `kwargs` and the provided offset.\n   */\n  private constructRequestBody(offset?: string): Record<string, any> {\n    return { ...this.kwargs, offset };\n  }\n\n  /**\n   * Sends the API request to Airtable and handles the response.\n   * Includes a timeout to prevent hanging on unresponsive requests.\n   *\n   * @param body - The request payload to be sent to the Airtable API.\n   * @returns A promise that resolves to an AirtableResponse object.\n   * @throws Will throw an error if the Airtable API request fails.\n   */\n  private async fetchRecords(\n    body: Record<string, any>\n  ): Promise<AirtableResponse> {\n    const url = `${AirtableLoader.BASE_URL}/${this.baseId}/${this.tableId}/listRecords`;\n    try {\n      const response = await fetch(url, {\n        method: \"POST\",\n        headers: {\n          Authorization: `Bearer ${this.apiToken}`,\n          \"Content-Type\": \"application/json\",\n        },\n        body: JSON.stringify(body),\n      });\n\n      if (!response.ok) {\n        throw new Error(\n          `Airtable API request failed with status ${response.status}: ${response.statusText}`\n        );\n      }\n\n      return (await response.json()) as AirtableResponse;\n    } catch (error) {\n      console.error(\"Error during fetch:\", error);\n      throw error;\n    }\n  }\n\n  /**\n   * Converts an Airtable record into a Document object with metadata.\n   *\n   * @param record - An Airtable record to convert.\n   * @returns A Document object with page content and metadata.\n   */\n  private createDocument(record: AirtableRecord): Document {\n    const metadata: Record<string, any> = {\n      source: `${this.baseId}_${this.tableId}`,\n      base_id: this.baseId,\n      table_id: this.tableId,\n      ...(this.kwargs.view && { view: this.kwargs.view }),\n    };\n    return new Document({ pageContent: JSON.stringify(record), metadata });\n  }\n}\n"],"mappings":";;;;;;;;;AA8BA,IAAa,iBAAb,MAAa,uBAAuBA,0DAAmB;CACrD,AAAiB;CAEjB,AAAiB;CAEjB,AAAiB;CAEjB,AAAiB;CAEjB,OAAwB,WAAW;CAEnC,AAAQ;;;;;;;;;;CAWR,YAAY,EAAE,SAAS,QAAQ,SAAS,CAAE,GAAyB,EAAE;EACnE,OAAO;EACP,KAAK,kEAAkC,qBAAqB,IAAI;EAChE,KAAK,UAAU;EACf,KAAK,SAAS;EACd,KAAK,SAAS;AAEd,MAAI,CAAC,KAAK,SACR,OAAM,IAAI,MACR;EAIJ,KAAK,cAAc,IAAIC,gDAAY;GAAE,YAAY;GAAG,gBAAgB;EAAG;CACxE;;;;;;CAOD,MAAa,OAA4B;EACvC,MAAMC,YAAwB,CAAE;EAChC,IAAIC;AAEJ,MAAI;AACF,MAAG;IACD,MAAM,OAAO,KAAK,qBAAqB,OAAO;IAC9C,MAAM,OAAO,MAAM,KAAK,YAAY,KAAK,MAAM,KAAK,aAAa,KAAK,CAAC;IACvE,KAAK,QAAQ,QAAQ,CAACC,WACpB,UAAU,KAAK,KAAK,eAAe,OAAO,CAAC,CAC5C;IACD,SAAS,KAAK;GACf,SAAQ;EACV,SAAQ,OAAO;GACd,QAAQ,MAAM,mCAAmC,MAAM;AACvD,SAAM,IAAI,MAAM;EACjB;AAED,SAAO;CACR;;;;;;;;CASD,OAAc,WAAqC;EACjD,IAAID;AACJ,MAAI;AACF,MAAG;IACD,MAAM,OAAO,KAAK,qBAAqB,OAAO;IAC9C,MAAM,OAAO,MAAM,KAAK,YAAY,KAAK,MAAM,KAAK,aAAa,KAAK,CAAC;AAEvE,SAAK,MAAM,UAAU,KAAK,SACxB,MAAM,KAAK,eAAe,OAAO;IAGnC,SAAS,KAAK;GACf,SAAQ;EACV,SAAQ,OAAO;GACd,QAAQ,MAAM,0CAA0C,MAAM;AAC9D,SAAM,IAAI,MAAM;EACjB;CACF;;;;;;;CAQD,AAAQ,qBAAqBE,QAAsC;AACjE,SAAO;GAAE,GAAG,KAAK;GAAQ;EAAQ;CAClC;;;;;;;;;CAUD,MAAc,aACZC,MAC2B;EAC3B,MAAM,MAAM,GAAG,eAAe,SAAS,CAAC,EAAE,KAAK,OAAO,CAAC,EAAE,KAAK,QAAQ,YAAY,CAAC;AACnF,MAAI;GACF,MAAM,WAAW,MAAM,MAAM,KAAK;IAChC,QAAQ;IACR,SAAS;KACP,eAAe,CAAC,OAAO,EAAE,KAAK,UAAU;KACxC,gBAAgB;IACjB;IACD,MAAM,KAAK,UAAU,KAAK;GAC3B,EAAC;AAEF,OAAI,CAAC,SAAS,GACZ,OAAM,IAAI,MACR,CAAC,wCAAwC,EAAE,SAAS,OAAO,EAAE,EAAE,SAAS,YAAY;AAIxF,UAAQ,MAAM,SAAS,MAAM;EAC9B,SAAQ,OAAO;GACd,QAAQ,MAAM,uBAAuB,MAAM;AAC3C,SAAM;EACP;CACF;;;;;;;CAQD,AAAQ,eAAeF,QAAkC;EACvD,MAAMG,WAAgC;GACpC,QAAQ,GAAG,KAAK,OAAO,CAAC,EAAE,KAAK,SAAS;GACxC,SAAS,KAAK;GACd,UAAU,KAAK;GACf,GAAI,KAAK,OAAO,QAAQ,EAAE,MAAM,KAAK,OAAO,KAAM;EACnD;AACD,SAAO,IAAIC,oCAAS;GAAE,aAAa,KAAK,UAAU,OAAO;GAAE;EAAU;CACtE;AACF"}