issue-create.formatter.ts•4.52 kB
/**
 * Issue create formatter
 */
import type { CreateIssueRequest } from "@features/jira/issues/use-cases/create-issue.use-case";
import type { StringFormatter } from "@features/jira/shared";
import { parseADF } from "@features/jira/shared/parsers/adf.parser";
/**
 * Builder class for formatting issue creation request sections
 */
class IssueCreateSectionBuilder {
  private sections: string[] = [];
  constructor() {
    this.sections = [];
  }
  /**
   * Add header section
   */
  addHeader(): this {
    this.sections.push("# 🆕 Creating New Issue");
    return this;
  }
  /**
   * Add basic required information
   */
  addBasicInformation(request: CreateIssueRequest): this {
    this.sections.push(`**Project:** ${request.fields.project.key}`);
    this.sections.push(`**Issue Type:** ${request.fields.issuetype.name}`);
    this.sections.push(`**Summary:** ${request.fields.summary}`);
    // Description (handle ADF format)
    if (request.fields.description) {
      this.sections.push("**Description:**");
      const descriptionText = parseADF(request.fields.description);
      this.sections.push(descriptionText);
    }
    return this;
  }
  /**
   * Add optional single-value fields
   */
  addOptionalFields(request: CreateIssueRequest): this {
    if (request.fields.priority) {
      this.sections.push(`**Priority:** ${request.fields.priority.name}`);
    }
    if (request.fields.assignee) {
      this.sections.push(`**Assignee:** ${request.fields.assignee.accountId}`);
    }
    if (request.fields.environment) {
      this.sections.push("**Environment:**");
      const environmentText = parseADF(request.fields.environment);
      this.sections.push(environmentText);
    }
    return this;
  }
  /**
   * Add array-based fields
   */
  addArrayFields(request: CreateIssueRequest): this {
    if (request.fields.labels && request.fields.labels.length > 0) {
      this.sections.push(`**Labels:** ${request.fields.labels.join(", ")}`);
    }
    if (request.fields.components && request.fields.components.length > 0) {
      const componentNames = request.fields.components
        .map((c) => c.name)
        .join(", ");
      this.sections.push(`**Components:** ${componentNames}`);
    }
    if (request.fields.fixVersions && request.fields.fixVersions.length > 0) {
      const versionNames = request.fields.fixVersions
        .map((v) => v.name)
        .join(", ");
      this.sections.push(`**Fix Versions:** ${versionNames}`);
    }
    return this;
  }
  /**
   * Add time tracking and project-related fields
   */
  addTimeAndProjectFields(request: CreateIssueRequest): this {
    if (request.fields.parent) {
      this.sections.push(`**Parent Issue:** ${request.fields.parent.key}`);
    }
    if (request.fields.timetracking?.originalEstimate) {
      this.sections.push(
        `**Original Estimate:** ${request.fields.timetracking.originalEstimate}`,
      );
    }
    if (request.fields.customfield_10016) {
      this.sections.push(
        `**Story Points:** ${request.fields.customfield_10016}`,
      );
    }
    return this;
  }
  /**
   * Add any custom fields not in the known fields set
   */
  addCustomFields(request: CreateIssueRequest): this {
    const knownFields = new Set([
      "project",
      "issuetype",
      "summary",
      "description",
      "priority",
      "assignee",
      "labels",
      "components",
      "fixVersions",
      "parent",
      "timetracking",
      "environment",
      "customfield_10016",
    ]);
    const customFields = Object.entries(request.fields).filter(
      ([key]) => !knownFields.has(key),
    );
    if (customFields.length > 0) {
      this.sections.push("**Custom Fields:**");
      for (const [key, value] of customFields) {
        this.sections.push(`• **${key}:** ${JSON.stringify(value)}`);
      }
    }
    return this;
  }
  /**
   * Build the final formatted string
   */
  build(): string {
    return this.sections.join("\n\n");
  }
}
/**
 * Formatter class for issue creation requests - formats for display
 */
export class IssueCreateFormatter
  implements StringFormatter<CreateIssueRequest>
{
  /**
   * Format an issue creation request for display
   */
  format(request: CreateIssueRequest): string {
    return new IssueCreateSectionBuilder()
      .addHeader()
      .addBasicInformation(request)
      .addOptionalFields(request)
      .addArrayFields(request)
      .addTimeAndProjectFields(request)
      .addCustomFields(request)
      .build();
  }
}