UNPKG

@gohcltech/bitbucket-mcp

Version:

Bitbucket integration for Claude via Model Context Protocol

527 lines 23.3 kB
/** * @fileoverview Issue-specific HTTP client for Bitbucket API operations. * * This module provides comprehensive issue tracking functionality including: * - Listing and filtering issues with various criteria * - Creating, updating, and deleting issues * - Managing issue assignments, voting, and watching * - Handling issue comments and discussions * - Working with components, milestones, and versions * - Advanced issue workflow operations * * Issues in Bitbucket provide bug tracking, feature requests, and task * management capabilities. They support categorization through components, * project planning through milestones, and release tracking through versions. */ import { BaseClient, BitbucketApiResponse } from './base-client.js'; import { Issue, IssueComment, Component, Milestone, Version } from '../types/issue/index.js'; /** * HTTP client for Bitbucket issue tracking operations. * * Provides comprehensive methods for managing issues, comments, and related * metadata. Supports advanced filtering, workflow operations, and project * management features including components, milestones, and versions. * * @example * ```typescript * const client = new IssueClient(oauthService); * * // Create a new bug report * const issue = await client.createIssue('workspace', 'repo', { * title: 'Login page crashes on mobile', * content: { raw: 'Detailed description of the bug...', markup: 'markdown' }, * kind: 'bug', * priority: 'major', * component: { name: 'frontend' } * }); * * // Assign and track the issue * await client.assignIssue('workspace', 'repo', issue.id, 'developer-username'); * await client.watchIssue('workspace', 'repo', issue.id); * * // Add progress comments * await client.addIssueComment('workspace', 'repo', issue.id, * 'Investigation started - reproduced on iOS 16'); * ``` */ export declare class IssueClient extends BaseClient { /** * Retrieves issues from a repository with comprehensive filtering options. * * Supports filtering by state, priority, kind, assignee, reporter, component, * milestone, version, and custom queries. Issues can be sorted by various * criteria and paginated for efficient retrieval. * * @param workspaceSlug - Unique identifier for the workspace * @param repoSlug - Unique identifier for the repository * @param params - Optional query parameters for filtering and pagination * @param params.state - Filter by issue state (new, open, resolved, on hold, invalid, duplicate, wontfix, closed) * @param params.kind - Filter by issue type (bug, enhancement, proposal, task) * @param params.priority - Filter by priority (trivial, minor, major, critical, blocker) * @param params.assignee - Filter by assignee username * @param params.reporter - Filter by reporter username * @param params.component - Filter by component name * @param params.milestone - Filter by milestone name * @param params.version - Filter by version name * @param params.sort - Sort order (created_on, updated_on, priority, votes) * @param params.limit - Maximum number of issues to return (1-100) * @returns Promise resolving to paginated issue list * @throws {AuthenticationError} If not authenticated * @throws {BitbucketApiError} If repository not found or request fails * * @example * ```typescript * // Get open bugs assigned to specific developer * const openBugs = await client.getIssues('workspace', 'repo', { * state: 'open', * kind: 'bug', * assignee: 'john.doe', * sort: 'priority' * }); * * // Get high priority issues for current milestone * const urgentIssues = await client.getIssues('workspace', 'repo', { * priority: 'critical', * milestone: 'v2.1.0', * state: 'open' * }); * ``` */ getIssues(workspaceSlug: string, repoSlug: string, params?: Record<string, string | number>): Promise<BitbucketApiResponse<Issue>>; /** * Retrieves all issues from a repository (all pages) with optional filtering. * * This method automatically handles pagination to return all issues * across multiple pages. Use this when you need a complete dataset * for analysis, reporting, or bulk operations. * * @param workspaceSlug - Unique identifier for the workspace * @param repoSlug - Unique identifier for the repository * @param params - Optional query parameters for filtering issues * @returns Promise resolving to array of all matching issues * @throws {AuthenticationError} If not authenticated * @throws {BitbucketApiError} If repository not found or request fails * * @example * ```typescript * // Get all issues for reporting * const allIssues = await client.getAllIssues('workspace', 'repo'); * * // Analyze issue distribution by component * const issuesByComponent = allIssues.reduce((groups, issue) => { * const component = issue.component?.name || 'Unassigned'; * groups[component] = (groups[component] || 0) + 1; * return groups; * }, {}); * * // Get all resolved issues for release notes * const resolvedIssues = await client.getAllIssues('workspace', 'repo', { * state: 'resolved', * version: 'v2.1.0' * }); * ``` */ getAllIssues(workspaceSlug: string, repoSlug: string, params?: Record<string, string | number>): Promise<Issue[]>; /** * Retrieves detailed information for a specific issue. * * Returns comprehensive issue data including title, description, state, * priority, assignments, metadata, and related components. This is useful * for displaying issue details or making workflow decisions. * * @param workspaceSlug - Unique identifier for the workspace * @param repoSlug - Unique identifier for the repository * @param issueId - Unique numeric identifier for the issue * @returns Promise resolving to detailed issue information * @throws {AuthenticationError} If not authenticated * @throws {BitbucketApiError} If issue not found or request fails * * @example * ```typescript * // Get issue details for display * const issue = await client.getIssue('workspace', 'repo', 42); * console.log(`Issue #${issue.id}: ${issue.title}`); * console.log(`State: ${issue.state}, Priority: ${issue.priority}`); * console.log(`Assignee: ${issue.assignee?.display_name || 'Unassigned'}`); * console.log(`Created: ${issue.created_on}`); * console.log(`Votes: ${issue.votes}`); * ``` */ getIssue(workspaceSlug: string, repoSlug: string, issueId: number): Promise<Issue>; /** * Creates a new issue in the repository. * * Creates an issue with specified title, description, and metadata. * Issues can be categorized using components, prioritized, assigned * to team members, and associated with milestones and versions. * * @param workspaceSlug - Unique identifier for the workspace * @param repoSlug - Unique identifier for the repository * @param payload - Issue creation data * @param payload.title - Issue title (required, max 255 characters) * @param payload.content - Issue description in markdown format * @param payload.kind - Issue type (bug, enhancement, proposal, task) * @param payload.priority - Issue priority (trivial, minor, major, critical, blocker) * @param payload.assignee - User to assign the issue to ({ username: 'user' }) * @param payload.component - Component for categorization ({ name: 'component' }) * @param payload.milestone - Milestone for project tracking ({ name: 'milestone' }) * @param payload.version - Version for release tracking ({ name: 'version' }) * @returns Promise resolving to the created issue details * @throws {AuthenticationError} If not authenticated * @throws {BitbucketApiError} If creation fails or validation errors occur * * @example * ```typescript * // Create a bug report * const bug = await client.createIssue('workspace', 'repo', { * title: 'Application crashes on startup', * content: { * raw: 'Steps to reproduce:\n1. Start app\n2. Click login\n3. App crashes', * markup: 'markdown' * }, * kind: 'bug', * priority: 'major', * component: { name: 'frontend' }, * assignee: { username: 'frontend-team-lead' } * }); * * // Create a feature request * const feature = await client.createIssue('workspace', 'repo', { * title: 'Add dark mode support', * content: { * raw: 'Users have requested dark mode for better accessibility', * markup: 'markdown' * }, * kind: 'enhancement', * priority: 'minor', * milestone: { name: 'v2.2.0' } * }); * ``` */ createIssue(workspaceSlug: string, repoSlug: string, payload: any): Promise<Issue>; /** * Updates an existing issue with new information or state changes. * * Allows modification of any issue field including title, description, * state, priority, assignments, and metadata. Only specified fields * will be updated, others remain unchanged. * * @param workspaceSlug - Unique identifier for the workspace * @param repoSlug - Unique identifier for the repository * @param issueId - Unique numeric identifier for the issue * @param payload - Issue update data (only specified fields will be updated) * @param payload.title - Updated issue title * @param payload.content - Updated issue description * @param payload.state - Updated state (new, open, resolved, closed, etc.) * @param payload.kind - Updated issue type * @param payload.priority - Updated priority level * @param payload.assignee - Updated assignee * @param payload.component - Updated component * @param payload.milestone - Updated milestone * @param payload.version - Updated version * @returns Promise resolving to the updated issue data * @throws {AuthenticationError} If not authenticated * @throws {BitbucketApiError} If issue not found or update fails * * @example * ```typescript * // Update issue state and priority * const updated = await client.updateIssue('workspace', 'repo', 42, { * state: 'resolved', * priority: 'minor' * }); * * // Reassign issue to different team member * await client.updateIssue('workspace', 'repo', 42, { * assignee: { username: 'new-developer' }, * title: 'Updated: Application crashes on startup' * }); * * // Close issue with resolution notes * await client.updateIssue('workspace', 'repo', 42, { * state: 'closed', * content: { * raw: 'Fixed in commit abc123. Root cause was null pointer exception.', * markup: 'markdown' * } * }); * ``` */ updateIssue(workspaceSlug: string, repoSlug: string, issueId: number, payload: any): Promise<Issue>; /** * Deletes an issue permanently from the repository. * * WARNING: This operation is irreversible and will delete all issue data * including comments, vote history, and watch subscriptions. Consider * closing the issue instead of deleting unless absolutely necessary. * * @param workspaceSlug - Unique identifier for the workspace * @param repoSlug - Unique identifier for the repository * @param issueId - Unique numeric identifier for the issue to delete * @returns Promise that resolves when deletion is complete * @throws {AuthenticationError} If not authenticated * @throws {BitbucketApiError} If issue not found or deletion fails * * @example * ```typescript * // Delete a spam or duplicate issue * await client.deleteIssue('workspace', 'repo', 42); * console.log('Issue deleted permanently'); * * // Better alternative: close instead of delete * await client.updateIssue('workspace', 'repo', 42, { * state: 'closed', * content: { raw: 'Closed as duplicate of #35', markup: 'markdown' } * }); * ``` */ deleteIssue(workspaceSlug: string, repoSlug: string, issueId: number): Promise<void>; /** * Retrieves comments for a specific issue. * * Returns all comments associated with the issue in chronological order. * Comments include author information, timestamps, and content in both * raw and rendered formats. * * @param workspaceSlug - Unique identifier for the workspace * @param repoSlug - Unique identifier for the repository * @param issueId - Unique numeric identifier for the issue * @param params - Optional query parameters for pagination * @param params.limit - Maximum number of comments to return (1-100) * @returns Promise resolving to paginated comment list * @throws {AuthenticationError} If not authenticated * @throws {BitbucketApiError} If issue not found or request fails * * @example * ```typescript * // Get comments for an issue * const comments = await client.getIssueComments('workspace', 'repo', 42); * console.log(`Found ${comments.values.length} comments`); * * // Display comment thread * comments.values.forEach(comment => { * console.log(`${comment.user.display_name} (${comment.created_on}):`); * console.log(comment.content.raw); * console.log('---'); * }); * ``` */ getIssueComments(workspaceSlug: string, repoSlug: string, issueId: number, params?: Record<string, string | number>): Promise<BitbucketApiResponse<IssueComment>>; /** * Adds a new comment to an issue. * * Creates a comment with markdown content for team discussion, * progress updates, or additional information. Comments support * full markdown formatting including links, code blocks, and lists. * * @param workspaceSlug - Unique identifier for the workspace * @param repoSlug - Unique identifier for the repository * @param issueId - Unique numeric identifier for the issue * @param content - Comment content in markdown format * @returns Promise resolving to the created comment details * @throws {AuthenticationError} If not authenticated * @throws {BitbucketApiError} If issue not found or comment creation fails * * @example * ```typescript * // Add a progress update * const comment = await client.addIssueComment('workspace', 'repo', 42, * 'Investigation complete. Root cause identified in auth module.'); * * // Add formatted comment with code * await client.addIssueComment('workspace', 'repo', 42, ` * ## Fix Applied * * Updated the validation logic: * * \`\`\`javascript * if (user && user.isValid()) { * return user.authenticate(); * } * \`\`\` * * This should resolve the crash reported in the issue. * `); * ``` */ addIssueComment(workspaceSlug: string, repoSlug: string, issueId: number, content: string): Promise<IssueComment>; /** * Retrieves all components configured for the repository. * * Components are used to categorize issues by functional area, * team responsibility, or system module. They help organize * and filter issues for better project management. * * @param workspaceSlug - Unique identifier for the workspace * @param repoSlug - Unique identifier for the repository * @returns Promise resolving to paginated component list * @throws {AuthenticationError} If not authenticated * @throws {BitbucketApiError} If repository not found or request fails * * @example * ```typescript * // Get all components for issue categorization * const components = await client.getComponents('workspace', 'repo'); * * console.log('Available components:'); * components.values.forEach(component => { * console.log(`- ${component.name}: ${component.description || 'No description'}`); * }); * * // Use component in issue creation * const frontendComponent = components.values.find(c => c.name === 'frontend'); * ``` */ getComponents(workspaceSlug: string, repoSlug: string): Promise<BitbucketApiResponse<Component>>; /** * Retrieves milestones configured for the repository. * * Milestones represent project goals, release targets, or time-based * objectives. They help track progress and organize issues by * project phases or release cycles. * * @param workspaceSlug - Unique identifier for the workspace * @param repoSlug - Unique identifier for the repository * @param params - Optional query parameters for filtering * @param params.state - Filter by milestone state (open, closed) * @returns Promise resolving to paginated milestone list * @throws {AuthenticationError} If not authenticated * @throws {BitbucketApiError} If repository not found or request fails * * @example * ```typescript * // Get active milestones * const milestones = await client.getMilestones('workspace', 'repo', { * state: 'open' * }); * * console.log('Active milestones:'); * milestones.values.forEach(milestone => { * console.log(`- ${milestone.name}: ${milestone.description}`); * console.log(` Due: ${milestone.due_on || 'No due date'}`); * }); * * // Use milestone in issue creation * const currentMilestone = milestones.values[0]; * ``` */ getMilestones(workspaceSlug: string, repoSlug: string, params?: Record<string, string>): Promise<BitbucketApiResponse<Milestone>>; /** * Retrieves versions configured for the repository. * * Versions represent software releases or deployment targets. * They help track which issues are resolved in specific releases * and plan future development cycles. * * @param workspaceSlug - Unique identifier for the workspace * @param repoSlug - Unique identifier for the repository * @param params - Optional query parameters for filtering * @param params.released - Filter by release status (true for released, false for unreleased) * @returns Promise resolving to paginated version list * @throws {AuthenticationError} If not authenticated * @throws {BitbucketApiError} If repository not found or request fails * * @example * ```typescript * // Get unreleased versions for planning * const unreleased = await client.getVersions('workspace', 'repo', { * released: false * }); * * console.log('Planned releases:'); * unreleased.values.forEach(version => { * console.log(`- ${version.name}: ${version.description}`); * console.log(` Release date: ${version.release_date || 'TBD'}`); * }); * * // Get all released versions for changelog * const released = await client.getVersions('workspace', 'repo', { * released: true * }); * ``` */ getVersions(workspaceSlug: string, repoSlug: string, params?: Record<string, string | boolean>): Promise<BitbucketApiResponse<Version>>; /** * Assigns an issue to a specific user for resolution. * * Updates the issue's assignee field to designate responsibility * for investigation and resolution. The assignee will receive * notifications about issue updates and changes. * * @param workspaceSlug - Unique identifier for the workspace * @param repoSlug - Unique identifier for the repository * @param issueId - Unique numeric identifier for the issue * @param assignee - Username of the user to assign the issue to * @returns Promise resolving to the updated issue data * @throws {AuthenticationError} If not authenticated * @throws {BitbucketApiError} If issue not found or assignment fails * * @example * ```typescript * // Assign bug to frontend specialist * const assignedIssue = await client.assignIssue('workspace', 'repo', 42, 'frontend-dev'); * console.log(`Issue assigned to ${assignedIssue.assignee.display_name}`); * * // Reassign to team lead for escalation * await client.assignIssue('workspace', 'repo', 42, 'team-lead'); * ``` */ assignIssue(workspaceSlug: string, repoSlug: string, issueId: number, assignee: string): Promise<Issue>; /** * Votes on an issue to show interest and support. * * Adds the authenticated user's vote to the issue, indicating * interest or priority. Vote counts help prioritize issues * and gauge community interest in features or bug fixes. * * @param workspaceSlug - Unique identifier for the workspace * @param repoSlug - Unique identifier for the repository * @param issueId - Unique numeric identifier for the issue * @returns Promise that resolves when vote is recorded * @throws {AuthenticationError} If not authenticated * @throws {BitbucketApiError} If issue not found or voting fails * * @example * ```typescript * // Vote for a feature request * await client.voteIssue('workspace', 'repo', 42); * console.log('Vote added - this will help prioritize the issue'); * * // Check vote count after voting * const issue = await client.getIssue('workspace', 'repo', 42); * console.log(`Issue now has ${issue.votes} votes`); * ``` */ voteIssue(workspaceSlug: string, repoSlug: string, issueId: number): Promise<void>; /** * Watches or unwatches an issue for notifications about changes. * * Subscribes the authenticated user to receive notifications * when the issue is updated, commented on, or state changes. * This helps stakeholders stay informed about issue progress. * * @param workspaceSlug - Unique identifier for the workspace * @param repoSlug - Unique identifier for the repository * @param issueId - Unique numeric identifier for the issue * @param watch - Whether to watch (true) or unwatch (false) the issue * @returns Promise that resolves when watch status is updated * @throws {AuthenticationError} If not authenticated * @throws {BitbucketApiError} If issue not found or watch operation fails * * @example * ```typescript * // Start watching a critical issue * await client.watchIssue('workspace', 'repo', 42, true); * console.log('Now watching issue - you will receive notifications'); * * // Stop watching resolved issue * await client.watchIssue('workspace', 'repo', 42, false); * console.log('No longer watching issue'); * * // Default behavior is to watch * await client.watchIssue('workspace', 'repo', 42); * ``` */ watchIssue(workspaceSlug: string, repoSlug: string, issueId: number, watch?: boolean): Promise<void>; } //# sourceMappingURL=issue-client.d.ts.map