UNPKG

@aashari/mcp-server-atlassian-jira

Version:

Node.js/TypeScript MCP server for Atlassian Jira. Equips AI systems (LLMs) with tools to list/get projects, search/get issues (using JQL/ID), and view dev info (commits, PRs). Connects AI capabilities directly into Jira project management and issue tracki

186 lines (185 loc) 6.15 kB
"use strict"; // Test comment to verify edit functionality Object.defineProperty(exports, "__esModule", { value: true }); exports.formatUrl = formatUrl; exports.formatHeading = formatHeading; exports.formatBulletList = formatBulletList; exports.formatSeparator = formatSeparator; exports.formatNumberedList = formatNumberedList; exports.formatDate = formatDate; exports.formatPagination = formatPagination; const logger_util_js_1 = require("./logger.util.js"); /** * Markdown formatting utilities */ /** * Standardized formatting utilities for consistent output across all CLI and Tool interfaces. * These functions should be used by all formatters to ensure consistent formatting. */ /** * Format a URL as a markdown link * @param url - URL to format * @param title - Link title * @returns Formatted markdown link */ function formatUrl(url, title) { if (!url) { return 'Not available'; } const linkTitle = title || url; return `[${linkTitle}](${url})`; } /** * Format a heading with consistent style * @param text - Heading text * @param level - Heading level (1-6) * @returns Formatted heading */ function formatHeading(text, level = 1) { const validLevel = Math.min(Math.max(level, 1), 6); const prefix = '#'.repeat(validLevel); return `${prefix} ${text}`; } /** * Format a list of key-value pairs as a bullet list * @param items - Object with key-value pairs * @param keyFormatter - Optional function to format keys * @returns Formatted bullet list */ function formatBulletList(items, keyFormatter) { const lines = []; for (const [key, value] of Object.entries(items)) { if (value === undefined || value === null) { continue; } const formattedKey = keyFormatter ? keyFormatter(key) : key; const formattedValue = formatValue(value); lines.push(`- **${formattedKey}**: ${formattedValue}`); } return lines.join('\n'); } /** * Format a value based on its type * @param value - Value to format * @returns Formatted value */ function formatValue(value) { if (value === undefined || value === null) { return 'Not available'; } if (value instanceof Date) { // Use toLocaleString for Dates try { return value.toLocaleString(); } catch { return 'Invalid date'; } } // Handle URL objects with url and title properties if (typeof value === 'object' && value !== null && 'url' in value) { const urlObj = value; if (typeof urlObj.url === 'string') { return formatUrl(urlObj.url, urlObj.title); } } if (typeof value === 'string') { // Check if it's a URL if (value.startsWith('http://') || value.startsWith('https://')) { return formatUrl(value); } // Check if it might be a date string and format it if (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(value)) { try { return new Date(value).toLocaleString(); } catch { return 'Invalid date string'; // Or return original string? } } return value; } if (typeof value === 'boolean') { return value ? 'Yes' : 'No'; } return String(value); } /** * Format a separator line * @returns Separator line */ function formatSeparator() { return '---'; } /** * Format a numbered list of items * @param items - Array of items to format * @param formatter - Function to format each item * @returns Formatted numbered list */ function formatNumberedList(items, formatter) { if (items.length === 0) { return 'No items.'; } return items .map((item, index) => formatter(item, index)) .join('\n\n' + formatSeparator() + '\n\n'); } /** * Format a date in a standardized way: YYYY-MM-DD HH:MM:SS UTC * @param dateInput - ISO date string, Date object, or timestamp number * @returns Formatted date string */ function formatDate(dateInput) { if (dateInput === undefined || dateInput === null) { return 'Not available'; } try { // Create Date object correctly from string, Date, or number (timestamp) const date = dateInput instanceof Date ? dateInput : new Date(dateInput); // Check if the date is valid after creation if (isNaN(date.getTime())) { return 'Invalid date input'; } // Format: YYYY-MM-DD HH:MM:SS UTC return date .toISOString() .replace('T', ' ') .replace(/\.\d+Z$/, ' UTC'); } catch { return 'Invalid date'; } } /** * Format pagination information in a standardized way for CLI output. * Includes separator, item counts, availability message, next page instructions, and timestamp. * @param pagination - The ResponsePagination object containing pagination details. * @returns Formatted pagination footer string for CLI. */ function formatPagination(pagination) { const methodLogger = logger_util_js_1.Logger.forContext('utils/formatter.util.ts', 'formatPagination'); const parts = [formatSeparator()]; // Start with separator const { count = 0, hasMore, nextCursor, total } = pagination; // Showing count and potentially total if (total !== undefined && total >= 0) { parts.push(`*Showing ${count} of ${total} total items.*`); } else if (count >= 0) { parts.push(`*Showing ${count} item${count !== 1 ? 's' : ''}.*`); } // More results availability if (hasMore) { parts.push('More results are available.'); } // Prompt for the next action (using next startAt value for Jira) if (hasMore && nextCursor) { // nextCursor holds the next startAt value for OFFSET pagination parts.push(`*Use --start-at ${nextCursor} to view more.*`); } // Add standard timestamp parts.push(`*Information retrieved at: ${formatDate(new Date())}*`); const result = parts.join('\n').trim(); // Join with newline methodLogger.debug(`Formatted pagination footer: ${result}`); return result; }