{"version":3,"file":"notionapi.cjs","names":["BaseDocumentLoader","AsyncCaller","Client","NotionToMarkdown","isFullBlock","yaml","Document","APIErrorCode"],"sources":["../../../src/document_loaders/web/notionapi.ts"],"sourcesContent":["import {\n  APIResponseError,\n  Client,\n  isFullBlock,\n  isFullPage,\n  iteratePaginatedAPI,\n  APIErrorCode,\n  isNotionClientError,\n  isFullDatabase,\n} from \"@notionhq/client\";\nimport { NotionToMarkdown } from \"notion-to-md\";\nimport { getBlockChildren } from \"notion-to-md/build/utils/notion.js\";\nimport type {\n  ListBlockChildrenResponseResults,\n  MdBlock,\n} from \"notion-to-md/build/types\";\nimport yaml from \"js-yaml\";\n\nimport { Document } from \"@langchain/core/documents\";\nimport { AsyncCaller } from \"@langchain/core/utils/async_caller\";\nimport { BaseDocumentLoader } from \"@langchain/core/document_loaders/base\";\n\n// oxlint-disable-next-line typescript/no-explicit-any\ntype GuardType<T> = T extends ((x: any, ...rest: any) => x is infer U)\n  ? U\n  : never;\n\nexport type GetBlockResponse = Parameters<typeof isFullBlock>[0];\nexport type GetPageResponse = Parameters<typeof isFullPage>[0];\nexport type GetDatabaseResponse = Parameters<typeof isFullDatabase>[0];\n\nexport type BlockObjectResponse = GuardType<typeof isFullBlock>;\nexport type PageObjectResponse = GuardType<typeof isFullPage>;\nexport type DatabaseObjectResponse = GuardType<typeof isFullDatabase>;\n\nexport type GetResponse =\n  | GetBlockResponse\n  | GetPageResponse\n  | GetDatabaseResponse\n  | APIResponseError;\n\nexport type PagePropertiesType = PageObjectResponse[\"properties\"];\nexport type PagePropertiesValue = PagePropertiesType[keyof PagePropertiesType];\n\nexport const isPageResponse = (res: GetResponse): res is GetPageResponse =>\n  !isNotionClientError(res) && res.object === \"page\";\nexport const isDatabaseResponse = (\n  res: GetResponse\n): res is GetDatabaseResponse =>\n  !isNotionClientError(res) && res.object === \"database\";\nexport const isErrorResponse = (res: GetResponse): res is APIResponseError =>\n  isNotionClientError(res);\n\nexport const isPage = (res: GetResponse): res is PageObjectResponse =>\n  isPageResponse(res) && isFullPage(res);\nexport const isDatabase = (res: GetResponse): res is DatabaseObjectResponse =>\n  isDatabaseResponse(res) && isFullDatabase(res);\n\nexport type OnDocumentLoadedCallback = (\n  current: number,\n  total: number,\n  currentTitle?: string,\n  rootTitle?: string\n) => void;\n\nexport type NotionAPILoaderOptions = {\n  clientOptions: ConstructorParameters<typeof Client>[0];\n  id: string;\n  callerOptions?: ConstructorParameters<typeof AsyncCaller>[0];\n  onDocumentLoaded?: OnDocumentLoadedCallback;\n  propertiesAsHeader?: boolean;\n};\n\n/**\n * A class that extends the BaseDocumentLoader class. It represents a\n * document loader for loading documents from Notion using the Notion API.\n * @example\n * ```typescript\n * const pageLoader = new NotionAPILoader({\n *   clientOptions: { auth: \"<NOTION_INTEGRATION_TOKEN>\" },\n *   id: \"<PAGE_ID>\",\n *   type: \"page\",\n * });\n * const pageDocs = await pageLoader.load();\n * const splitDocs = await splitter.splitDocuments(pageDocs);\n *\n * const dbLoader = new NotionAPILoader({\n *   clientOptions: { auth: \"<NOTION_INTEGRATION_TOKEN>\" },\n *   id: \"<DATABASE_ID>\",\n *   type: \"database\",\n *   propertiesAsHeader: true,\n * });\n * const dbDocs = await dbLoader.load();\n * ```\n */\nexport class NotionAPILoader extends BaseDocumentLoader {\n  private caller: AsyncCaller;\n\n  private notionClient: Client;\n\n  private n2mClient: NotionToMarkdown;\n\n  private id: string;\n\n  private pageQueue: string[];\n\n  private pageCompleted: string[];\n\n  public pageQueueTotal: number;\n\n  private documents: Document[];\n\n  private rootTitle: string;\n\n  private onDocumentLoaded: OnDocumentLoadedCallback;\n\n  private propertiesAsHeader: boolean;\n\n  constructor(options: NotionAPILoaderOptions) {\n    super();\n\n    this.caller = new AsyncCaller({\n      maxConcurrency: 64,\n      ...options.callerOptions,\n    });\n    this.notionClient = new Client({\n      logger: () => {}, // Suppress Notion SDK logger\n      ...options.clientOptions,\n    });\n    this.n2mClient = new NotionToMarkdown({\n      notionClient: this.notionClient,\n      config: { parseChildPages: false, convertImagesToBase64: false },\n    });\n    this.id = options.id;\n    this.pageQueue = [];\n    this.pageCompleted = [];\n    this.pageQueueTotal = 0;\n    this.documents = [];\n    this.rootTitle = \"\";\n    this.onDocumentLoaded = options.onDocumentLoaded ?? ((_ti, _cu) => {});\n    this.propertiesAsHeader = options.propertiesAsHeader || false;\n  }\n\n  /**\n   * Adds a selection of page ids to the pageQueue and removes duplicates.\n   * @param items An array of string ids\n   */\n  private addToQueue(...items: string[]) {\n    const deDuped = items.filter(\n      (item) => !this.pageCompleted.concat(this.pageQueue).includes(item)\n    );\n    this.pageQueue.push(...deDuped);\n    this.pageQueueTotal += deDuped.length;\n  }\n\n  /**\n   * Parses a Notion GetResponse object (page or database) and returns a string of the title.\n   * @param obj The Notion GetResponse object to parse.\n   * @returns The string of the title.\n   */\n  private getTitle(obj: GetResponse) {\n    if (isPage(obj)) {\n      const titleProp = Object.values(obj.properties).find(\n        (prop) => prop.type === \"title\"\n      );\n      if (titleProp) return this.getPropValue(titleProp);\n    }\n    if (isDatabase(obj))\n      return obj.title\n        .map((v) =>\n          this.n2mClient.annotatePlainText(v.plain_text, v.annotations)\n        )\n        .join(\"\");\n    return null;\n  }\n\n  /**\n   * Parses the property type and returns a string\n   * @param page The Notion page property to parse.\n   * @returns A string of parsed property.\n   */\n  private getPropValue(prop: PagePropertiesValue) {\n    switch (prop.type) {\n      case \"number\": {\n        const propNumber = prop[prop.type];\n        return propNumber !== null ? propNumber.toString() : \"\";\n      }\n      case \"url\":\n        return prop[prop.type] || \"\";\n      case \"select\":\n        return prop[prop.type]?.name ?? \"\";\n      case \"multi_select\":\n        return `[${prop[prop.type].map((v) => `\"${v.name}\"`).join(\", \")}]`;\n      case \"status\":\n        return prop[prop.type]?.name ?? \"\";\n      case \"date\":\n        return `${prop[prop.type]?.start ?? \"\"}${\n          prop[prop.type]?.end ? ` - ${prop[prop.type]?.end}` : \"\"\n        }`;\n      case \"email\":\n        return prop[prop.type] || \"\";\n      case \"phone_number\":\n        return prop[prop.type] || \"\";\n      case \"checkbox\":\n        return prop[prop.type].toString();\n      case \"files\":\n        return `[${prop[prop.type].map((v) => `\"${v.name}\"`).join(\", \")}]`;\n      case \"created_by\":\n        return `[\"${prop[prop.type].object}\", \"${prop[prop.type].id}\"]`;\n      case \"created_time\":\n        return prop[prop.type];\n      case \"last_edited_by\":\n        return `[\"${prop[prop.type].object}\", \"${prop[prop.type].id}\"]`;\n      case \"last_edited_time\":\n        return prop[prop.type];\n      case \"title\":\n        return prop[prop.type]\n          .map((v) =>\n            this.n2mClient.annotatePlainText(v.plain_text, v.annotations)\n          )\n          .join(\"\");\n      case \"rich_text\":\n        return prop[prop.type]\n          .map((v) =>\n            this.n2mClient.annotatePlainText(v.plain_text, v.annotations)\n          )\n          .join(\"\");\n      case \"people\":\n        return `[${prop[prop.type]\n          .map((v) => `[\"${v.object}\", \"${v.id}\"]`)\n          .join(\", \")}]`;\n      case \"unique_id\":\n        return `${prop[prop.type].prefix || \"\"}${prop[prop.type].number}`;\n      case \"relation\":\n        return `[${prop[prop.type].map((v) => `\"${v.id}\"`).join(\", \")}]`;\n      default:\n        return `Unsupported type: ${prop.type}`;\n    }\n  }\n\n  /**\n   * Parses the properties of a Notion page and returns them as key-value\n   * pairs.\n   * @param page The Notion page to parse.\n   * @returns An object containing the parsed properties as key-value pairs.\n   */\n  private parsePageProperties(page: PageObjectResponse) {\n    return Object.entries(page.properties).reduce(\n      (accum, [propName, prop]) => {\n        const value = this.getPropValue(prop);\n        const props = { ...accum, [propName]: value };\n        return prop.type === \"title\" ? { ...props, _title: value } : props;\n      },\n      {} as { [key: string]: string }\n    );\n  }\n\n  /**\n   * Parses the details of a Notion page and returns them as an object.\n   * @param page The Notion page to parse.\n   * @returns An object containing the parsed details of the page.\n   */\n  private parsePageDetails(page: PageObjectResponse) {\n    const { id, ...rest } = page;\n    return {\n      ...rest,\n      notionId: id,\n      properties: this.parsePageProperties(page),\n    };\n  }\n\n  /**\n   * Loads a Notion block and returns it as an MdBlock object.\n   * @param block The Notion block to load.\n   * @returns A Promise that resolves to an MdBlock object.\n   */\n  private async loadBlock(block: BlockObjectResponse): Promise<MdBlock> {\n    const mdBlock: MdBlock = {\n      type: block.type,\n      blockId: block.id,\n      parent: await this.caller.call(() =>\n        this.n2mClient.blockToMarkdown(block)\n      ),\n      children: [],\n    };\n\n    if (block.has_children) {\n      const block_id =\n        block.type === \"synced_block\" &&\n        block.synced_block?.synced_from?.block_id\n          ? block.synced_block.synced_from.block_id\n          : block.id;\n\n      const childBlocks = await this.loadBlocks(\n        await this.caller.call(() =>\n          getBlockChildren(this.notionClient, block_id, null)\n        )\n      );\n\n      mdBlock.children = childBlocks;\n    }\n\n    return mdBlock;\n  }\n\n  /**\n   * Loads Notion blocks and their children recursively.\n   * @param blocksResponse The response from the Notion API containing the blocks to load.\n   * @returns A Promise that resolves to an array containing the loaded MdBlocks.\n   */\n  private async loadBlocks(\n    blocksResponse: ListBlockChildrenResponseResults\n  ): Promise<MdBlock[]> {\n    const blocks = blocksResponse.filter(isFullBlock);\n\n    // Add child pages to queue\n    const childPages = blocks\n      .filter((block) => block.type.includes(\"child_page\"))\n      .map((block) => block.id);\n    if (childPages.length > 0) this.addToQueue(...childPages);\n\n    // Add child database pages to queue\n    const childDatabases = blocks\n      .filter((block) => block.type.includes(\"child_database\"))\n      .map((block) => this.caller.call(() => this.loadDatabase(block.id)));\n\n    // Load this block and child blocks\n    const loadingMdBlocks = blocks\n      .filter((block) => ![\"child_page\", \"child_database\"].includes(block.type))\n      .map((block) => this.loadBlock(block));\n\n    const [mdBlocks] = await Promise.all([\n      Promise.all(loadingMdBlocks),\n      Promise.all(childDatabases),\n    ]);\n\n    return mdBlocks;\n  }\n\n  /**\n   * Loads a Notion page and its child documents, then adds it to the completed documents array.\n   * @param page The Notion page or page ID to load.\n   */\n  private async loadPage(page: string | PageObjectResponse) {\n    // Check page is a page ID or a PageObjectResponse\n    const [pageData, pageId] =\n      typeof page === \"string\"\n        ? [\n            this.caller.call(() =>\n              this.notionClient.pages.retrieve({ page_id: page })\n            ),\n            page,\n          ]\n        : [page, page.id];\n\n    const [pageDetails, pageBlocks] = await Promise.all([\n      pageData,\n      this.caller.call(() => getBlockChildren(this.notionClient, pageId, null)),\n    ]);\n\n    if (!isFullPage(pageDetails)) {\n      this.pageCompleted.push(pageId);\n      return;\n    }\n\n    const mdBlocks = await this.loadBlocks(pageBlocks);\n    const mdStringObject = this.n2mClient.toMarkdownString(mdBlocks);\n\n    let pageContent = mdStringObject.parent;\n    const metadata = this.parsePageDetails(pageDetails);\n\n    if (this.propertiesAsHeader) {\n      pageContent =\n        `---\\n` +\n        `${yaml.dump(metadata.properties)}` +\n        `---\\n\\n` +\n        `${pageContent ?? \"\"}`;\n    }\n\n    if (!pageContent) {\n      this.pageCompleted.push(pageId);\n      return;\n    }\n\n    const pageDocument = new Document({ pageContent, metadata });\n\n    this.documents.push(pageDocument);\n    this.pageCompleted.push(pageId);\n    this.onDocumentLoaded(\n      this.documents.length,\n      this.pageQueueTotal,\n      this.getTitle(pageDetails) || undefined,\n      this.rootTitle\n    );\n  }\n\n  /**\n   * Loads a Notion database and adds it's pages to the queue.\n   * @param id The ID of the Notion database to load.\n   */\n  private async loadDatabase(id: string) {\n    try {\n      for await (const page of iteratePaginatedAPI(\n        this.notionClient.databases.query,\n        {\n          database_id: id,\n          page_size: 50,\n        }\n      )) {\n        this.addToQueue(page.id);\n      }\n    } catch (e) {\n      console.log(e);\n      // TODO: Catch and report api request errors\n    }\n  }\n\n  /**\n   * Loads the documents from Notion based on the specified options.\n   * @returns A Promise that resolves to an array of Documents.\n   */\n  async load(): Promise<Document[]> {\n    const resPagePromise = this.notionClient.pages\n      .retrieve({ page_id: this.id })\n      .then((res) => {\n        this.addToQueue(this.id);\n        return res;\n      })\n      .catch((error: APIResponseError) => error);\n\n    const resDatabasePromise = this.notionClient.databases\n      .retrieve({ database_id: this.id })\n      .then(async (res) => {\n        await this.loadDatabase(this.id);\n        return res;\n      })\n      .catch((error: APIResponseError) => error);\n\n    const [resPage, resDatabase] = await Promise.all([\n      resPagePromise,\n      resDatabasePromise,\n    ]);\n\n    // Check if both resPage and resDatabase resulted in error responses\n    const errors = [resPage, resDatabase].filter(isErrorResponse);\n    if (errors.length === 2) {\n      if (errors.every((e) => e.code === APIErrorCode.ObjectNotFound)) {\n        throw new AggregateError([\n          Error(\n            `Could not find object with ID: ${this.id}. Make sure the relevant pages and databases are shared with your integration.`\n          ),\n          ...errors,\n        ]);\n      }\n      throw new AggregateError(errors);\n    }\n\n    this.rootTitle =\n      this.getTitle(resPage) || this.getTitle(resDatabase) || this.id;\n\n    let pageId = this.pageQueue.shift();\n    while (pageId) {\n      await this.loadPage(pageId);\n      pageId = this.pageQueue.shift();\n    }\n    return this.documents;\n  }\n}\n"],"mappings":"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"}