{"version":3,"file":"jira.cjs","names":["adf: ADFNode | null | undefined","node: ADFNode","issues: JiraIssue[]","issue: JiraIssue","Document","BaseDocumentLoader","allIssues: JiraIssue[]","date: Date | undefined","data: JiraAPIResponse"],"sources":["../../../src/document_loaders/web/jira.ts"],"sourcesContent":["import { Document } from \"@langchain/core/documents\";\nimport { BaseDocumentLoader } from \"@langchain/core/document_loaders/base\";\n\nexport type JiraStatusCategory = {\n  self: string;\n  id: number;\n  key: string;\n  colorName: string;\n  name: string;\n};\n\nexport type JiraStatus = {\n  self: string;\n  description: string;\n  iconUrl: string;\n  name: string;\n  id: string;\n  statusCategory: JiraStatusCategory;\n};\n\nexport type JiraUser = {\n  accountId: string;\n  accountType: string;\n  active: boolean;\n  avatarUrls: {\n    \"16x16\": string;\n    \"24x24\": string;\n    \"32x32\": string;\n    \"48x48\": string;\n  };\n  displayName: string;\n  emailAddress: string;\n  self: string;\n  timeZone: string;\n};\n\nexport type JiraIssueType = {\n  avatarId: number;\n  description: string;\n  entityId: string;\n  hierarchyLevel: number;\n  iconUrl: string;\n  id: string;\n  name: string;\n  self: string;\n  subtask: boolean;\n};\n\nexport type JiraPriority = {\n  iconUrl: string;\n  id: string;\n  name: string;\n  self: string;\n};\n\nexport type JiraProgress = {\n  progress: number;\n  total: number;\n  percent?: number;\n};\n\nexport type JiraProject = {\n  avatarUrls: {\n    \"16x16\": string;\n    \"24x24\": string;\n    \"32x32\": string;\n    \"48x48\": string;\n  };\n  id: string;\n  key: string;\n  name: string;\n  projectTypeKey: string;\n  self: string;\n  simplified: boolean;\n};\n\nexport type JiraSubTask = {\n  id: string;\n  key: string;\n  self: string;\n  fields: {\n    issuetype: JiraIssueType;\n    priority: JiraPriority;\n    status: JiraStatus;\n    summary: string;\n  };\n};\n\nexport type JiraIssueLinkType = {\n  id: string;\n  name: string;\n  inward: string;\n  outward: string;\n  self: string;\n};\n\nexport type JiraBriefIssue = {\n  id: string;\n  key: string;\n  self: string;\n  fields: {\n    summary: string;\n    status: JiraStatus;\n    priority: JiraPriority;\n    issuetype: JiraIssueType;\n  };\n};\n\nexport type JiraIssueLink = {\n  id: string;\n  self: string;\n  type: JiraIssueLinkType;\n  inwardIssue?: JiraBriefIssue;\n  outwardIssue?: JiraBriefIssue;\n};\n\nexport type JiraIssue = {\n  expand: string;\n  id: string;\n  self: string;\n  key: string;\n  fields: {\n    assignee?: JiraUser;\n    created: string;\n    description: ADFNode;\n    issuelinks: JiraIssueLink[];\n    issuetype: JiraIssueType;\n    labels?: string[];\n    priority: JiraPriority;\n    progress: JiraProgress;\n    project: JiraProject;\n    reporter?: JiraUser;\n    creator: JiraUser;\n    resolutiondate?: string;\n    status: JiraStatus;\n    subtasks: JiraSubTask[];\n    summary: string;\n    timeestimate?: number;\n    timespent?: number;\n    updated: string;\n    duedate?: string;\n    parent?: JiraBriefIssue;\n  };\n};\n\nexport type JiraAPIResponse = {\n  expand: string;\n  startAt: number;\n  maxResults: number;\n  total: number;\n  issues: JiraIssue[];\n};\n\nexport interface ADFNode {\n  type: string;\n  text?: string;\n  content?: ADFNode[];\n}\n\nexport interface ADFDocument extends ADFNode {\n  type: \"doc\";\n  version: number;\n  content: ADFNode[];\n}\n\nexport function adfToText(adf: ADFNode | null | undefined): string {\n  if (!adf || !adf.content) return \"\";\n  const recur = (node: ADFNode): string => {\n    if (node.text) return node.text;\n    if (node.content) return node.content.map(recur).join(\"\");\n    return \"\";\n  };\n  return recur(adf).trim();\n}\n\n/**\n * Interface representing the parameters for configuring the\n * JiraDocumentConverter.\n */\nexport interface JiraDocumentConverterParams {\n  host: string;\n  projectKey: string;\n}\n\n/**\n * Class responsible for converting Jira issues to Document objects\n */\nexport class JiraDocumentConverter {\n  public readonly host: string;\n\n  public readonly projectKey: string;\n\n  constructor({ host, projectKey }: JiraDocumentConverterParams) {\n    this.host = host;\n    this.projectKey = projectKey;\n  }\n\n  public convertToDocuments(issues: JiraIssue[]): Document[] {\n    return issues.map((issue) => this.documentFromIssue(issue));\n  }\n\n  private documentFromIssue(issue: JiraIssue): Document {\n    return new Document({\n      pageContent: this.formatIssueInfo({\n        issue,\n        host: this.host,\n      }),\n      metadata: {\n        id: issue.id,\n        host: this.host,\n        projectKey: this.projectKey,\n      },\n    });\n  }\n\n  private formatIssueInfo({\n    issue,\n    host,\n  }: {\n    issue: JiraIssue;\n    host: string;\n  }): string {\n    let text = `Issue: ${this.formatMainIssueInfoText({ issue, host })}\\n`;\n    text += `Project: ${issue.fields.project.name} (${issue.fields.project.key}, ID ${issue.fields.project.id})\\n`;\n    text += `Status: ${issue.fields.status.name}\\n`;\n    text += `Priority: ${issue.fields.priority.name}\\n`;\n    text += `Type: ${issue.fields.issuetype.name}\\n`;\n    text += `Creator: ${issue.fields.creator?.displayName}\\n`;\n\n    if (issue.fields.labels && issue.fields.labels.length > 0) {\n      text += `Labels: ${issue.fields.labels.join(\", \")}\\n`;\n    }\n\n    text += `Created: ${issue.fields.created}\\n`;\n    text += `Updated: ${issue.fields.updated}\\n`;\n\n    if (issue.fields.reporter) {\n      text += `Reporter: ${issue.fields.reporter.displayName}\\n`;\n    }\n\n    text += `Assignee: ${issue.fields.assignee?.displayName ?? \"Unassigned\"}\\n`;\n\n    if (issue.fields.duedate) {\n      text += `Due Date: ${issue.fields.duedate}\\n`;\n    }\n\n    if (issue.fields.timeestimate) {\n      text += `Time Estimate: ${issue.fields.timeestimate}\\n`;\n    }\n\n    if (issue.fields.timespent) {\n      text += `Time Spent: ${issue.fields.timespent}\\n`;\n    }\n\n    if (issue.fields.resolutiondate) {\n      text += `Resolution Date: ${issue.fields.resolutiondate}\\n`;\n    }\n\n    if (issue.fields.description) {\n      text += `Description: ${issue.fields.description}\\n`;\n    }\n\n    if (issue.fields.progress?.percent) {\n      text += `Progress: ${issue.fields.progress.percent}%\\n`;\n    }\n\n    if (issue.fields.parent) {\n      text += `Parent Issue: ${this.formatMainIssueInfoText({\n        issue: issue.fields.parent,\n        host,\n      })}\\n`;\n    }\n\n    if (issue.fields.subtasks?.length > 0) {\n      text += `Subtasks:\\n`;\n      issue.fields.subtasks.forEach((subtask) => {\n        text += `  - ${this.formatMainIssueInfoText({\n          issue: subtask,\n          host,\n        })}\\n`;\n      });\n    }\n\n    if (issue.fields.issuelinks?.length > 0) {\n      text += `Issue Links:\\n`;\n      issue.fields.issuelinks.forEach((link) => {\n        text += `  - ${link.type.name}\\n`;\n        if (link.inwardIssue) {\n          text += `    - ${this.formatMainIssueInfoText({\n            issue: link.inwardIssue,\n            host,\n          })}\\n`;\n        }\n        if (link.outwardIssue) {\n          text += `    - ${this.formatMainIssueInfoText({\n            issue: link.outwardIssue,\n            host,\n          })}\\n`;\n        }\n      });\n    }\n\n    return text;\n  }\n\n  private getLinkToIssue({\n    issueKey,\n    host,\n  }: {\n    issueKey: string;\n    host: string;\n  }): string {\n    return `${host}/browse/${issueKey}`;\n  }\n\n  private formatMainIssueInfoText({\n    issue,\n    host,\n  }: {\n    issue: JiraIssue | JiraBriefIssue;\n    host: string;\n  }): string {\n    const link = this.getLinkToIssue({\n      issueKey: issue.key,\n      host,\n    });\n\n    const text = `${issue.key} (ID ${issue.id}) - ${issue.fields.summary} (${link})`;\n\n    return text;\n  }\n}\n\n/**\n * Interface representing the parameters for configuring the\n * JiraProjectLoader.\n */\nexport interface JiraProjectLoaderParams {\n  host: string;\n  projectKey: string;\n  username?: string;\n  accessToken?: string;\n  personalAccessToken?: string;\n  limitPerRequest?: number;\n  createdAfter?: Date;\n  filterFn?: (issue: JiraIssue) => boolean;\n}\n\nconst API_ENDPOINTS = {\n  SEARCH: \"/rest/api/3/search/jql\",\n};\n\n/**\n * Class representing a document loader for loading pages from Confluence.\n */\nexport class JiraProjectLoader extends BaseDocumentLoader {\n  private readonly accessToken?: string;\n\n  public readonly host: string;\n\n  public readonly projectKey: string;\n\n  public readonly username?: string;\n\n  public readonly limitPerRequest: number;\n\n  private readonly createdAfter?: Date;\n\n  private readonly filterFn?: (issue: JiraIssue) => boolean;\n\n  private readonly documentConverter: JiraDocumentConverter;\n\n  private readonly personalAccessToken?: string;\n\n  constructor({\n    host,\n    projectKey,\n    username,\n    accessToken,\n    limitPerRequest = 100,\n    createdAfter,\n    personalAccessToken,\n    filterFn,\n  }: JiraProjectLoaderParams) {\n    super();\n    this.host = host;\n    this.projectKey = projectKey;\n    this.username = username;\n    this.accessToken = accessToken;\n    this.limitPerRequest = limitPerRequest;\n    this.createdAfter = createdAfter;\n    this.documentConverter = new JiraDocumentConverter({ host, projectKey });\n    this.personalAccessToken = personalAccessToken;\n    this.filterFn = filterFn;\n  }\n\n  private buildAuthorizationHeader(): string {\n    if (this.personalAccessToken) {\n      return `Bearer ${this.personalAccessToken}`;\n    }\n    return `Basic ${Buffer.from(\n      `${this.username}:${this.accessToken}`\n    ).toString(\"base64\")}`;\n  }\n\n  public async load(): Promise<Document[]> {\n    try {\n      const allJiraIssues = await this.loadAsIssues();\n      const filtered = allJiraIssues.filter((issue) => {\n        if (this.filterFn) {\n          return this.filterFn(issue);\n        }\n        return true;\n      });\n      return this.documentConverter.convertToDocuments(filtered);\n    } catch (error) {\n      console.error(\"Error:\", error);\n      return [];\n    }\n  }\n\n  public async loadAsIssues(): Promise<JiraIssue[]> {\n    const allIssues: JiraIssue[] = [];\n\n    for await (const issues of this.fetchIssues()) {\n      allIssues.push(...issues);\n    }\n\n    return allIssues;\n  }\n\n  protected toJiraDateString(date: Date | undefined): string | undefined {\n    if (!date) {\n      return undefined;\n    }\n    const year = date.getFullYear();\n    const month = String(date.getMonth() + 1).padStart(2, \"0\");\n    const dayOfMonth = String(date.getDate()).padStart(2, \"0\");\n    return `${year}-${month}-${dayOfMonth}`;\n  }\n\n  protected async *fetchIssues(): AsyncIterable<JiraIssue[]> {\n    const authorizationHeader = this.buildAuthorizationHeader();\n    const url = `${this.host}${API_ENDPOINTS.SEARCH}`;\n    const createdAfterAsString = this.toJiraDateString(this.createdAfter);\n    let startAt = 0;\n\n    while (true) {\n      try {\n        const jqlProps = [\n          `project=${this.projectKey}`,\n          ...(createdAfterAsString\n            ? [`created>= \"${createdAfterAsString}\"`]\n            : []),\n        ];\n        const jql = `${jqlProps.join(\" AND \")} ORDER BY created ASC, key ASC`;\n\n        const params = new URLSearchParams({\n          jql,\n          startAt: `${startAt}`,\n          maxResults: `${this.limitPerRequest}`,\n          fields: \"*all\",\n        });\n        const pageUrl = `${url}?${params}`;\n\n        const options = {\n          method: \"GET\",\n          headers: {\n            Authorization: authorizationHeader,\n            Accept: \"application/json\",\n          },\n        };\n\n        const response = await fetch(pageUrl, options);\n        const data: JiraAPIResponse = await response.json();\n\n        if (!data.issues || data.issues.length === 0) break;\n\n        const allIssues = [];\n        for (const issue of data.issues) {\n          allIssues.push(issue);\n        }\n\n        if (allIssues.length > 0) yield allIssues;\n\n        startAt += this.limitPerRequest;\n\n        if (data.issues.length < this.limitPerRequest) break;\n      } catch (error) {\n        console.error(\"Error fetching Jira issues:\", error);\n        yield [];\n        break;\n      }\n    }\n  }\n}\n"],"mappings":"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"}