UNPKG

@gohcltech/bitbucket-mcp

Version:

Bitbucket integration for Claude via Model Context Protocol

465 lines 20.5 kB
/** * @fileoverview Main Bitbucket client facade that composes all domain-specific clients. * * This module provides the primary interface for interacting with the Bitbucket API * through a facade pattern that delegates operations to specialized domain clients. * It maintains backward compatibility while providing a cleaner, more organized structure. * * Usage patterns: * - client.workspaces.list() * - client.repositories.create(workspace, name, config) * - client.branches.list(workspace, repo) * - client.pullRequests.create(workspace, repo, prData) * - client.commits.getDiff(workspace, repo, hash) * - client.issues.create(workspace, repo, issueData) * */ import { getLogger } from '../logger.js'; import { WorkspaceClient } from './workspace-client.js'; import { RepositoryClient } from './repository-client.js'; import { BranchClient } from './branch-client.js'; import { PullRequestClient } from './pull-request-client.js'; import { CommitClient } from './commit-client.js'; import { IssueClient } from './issue-client.js'; /** * Main Bitbucket API client facade. * * This class provides a unified interface to all Bitbucket API operations * through domain-specific client instances. Each domain client handles * its own specialized operations while sharing common infrastructure * from the BaseClient. * * The facade pattern allows for: * - Clean separation of concerns by domain * - Consistent error handling and logging * - Shared authentication and rate limiting * - Backward compatibility with existing code * - Easy testing and mocking of specific domains */ export class BitbucketClient { /** Domain-specific client instances */ workspaces; repositories; branches; pullRequests; commits; issues; /** Logger instance for client-level operations */ logger = getLogger(); /** * Creates a new Bitbucket API client facade. * * Initializes all domain-specific clients with the shared authentication service, * ensuring consistent authentication and configuration across all operations. * * @param authService - Authentication service for token management */ constructor(authService) { // Initialize all domain clients with the shared authentication service this.workspaces = new WorkspaceClient(authService); this.repositories = new RepositoryClient(authService); this.branches = new BranchClient(authService); this.pullRequests = new PullRequestClient(authService); this.commits = new CommitClient(authService); this.issues = new IssueClient(authService); this.logger.info('BitbucketClient initialized with domain-specific clients', { domains: ['workspaces', 'repositories', 'branches', 'pullRequests', 'commits', 'issues'], }); } // ============================================================================= // BACKWARD COMPATIBILITY METHODS // ============================================================================= // These methods maintain compatibility with the existing API while delegating // to the appropriate domain clients. They can be gradually deprecated in favor // of the domain-specific interfaces. /** * @deprecated Use client.workspaces.getWorkspaces() instead */ async getWorkspaces() { this.logger.debug('Using deprecated getWorkspaces method, consider using client.workspaces.getWorkspaces()'); return this.workspaces.getWorkspaces(); } /** * @deprecated Use client.workspaces.getAllWorkspaces() instead */ async getAllWorkspaces() { this.logger.debug('Using deprecated getAllWorkspaces method, consider using client.workspaces.getAllWorkspaces()'); return this.workspaces.getAllWorkspaces(); } /** * @deprecated Use client.workspaces.getWorkspace() instead */ async getWorkspace(workspaceSlug) { this.logger.debug('Using deprecated getWorkspace method, consider using client.workspaces.getWorkspace()'); return this.workspaces.getWorkspace(workspaceSlug); } /** * @deprecated Use client.repositories.getRepositories() instead */ async getRepositories(workspaceSlug) { this.logger.debug('Using deprecated getRepositories method, consider using client.repositories.getRepositories()'); return this.repositories.getRepositories(workspaceSlug); } /** * @deprecated Use client.repositories.getAllRepositories() instead */ async getAllRepositories(workspaceSlug) { this.logger.debug('Using deprecated getAllRepositories method, consider using client.repositories.getAllRepositories()'); return this.repositories.getAllRepositories(workspaceSlug); } /** * @deprecated Use client.repositories.getRepository() instead */ async getRepository(workspaceSlug, repoSlug) { this.logger.debug('Using deprecated getRepository method, consider using client.repositories.getRepository()'); return this.repositories.getRepository(workspaceSlug, repoSlug); } /** * @deprecated Use client.repositories.createRepository() instead */ async createRepository(workspaceSlug, name, payload) { this.logger.debug('Using deprecated createRepository method, consider using client.repositories.createRepository()'); return this.repositories.createRepository(workspaceSlug, name, payload); } /** * @deprecated Use client.repositories.updateRepository() instead */ async updateRepository(workspaceSlug, repoSlug, payload) { this.logger.debug('Using deprecated updateRepository method, consider using client.repositories.updateRepository()'); return this.repositories.updateRepository(workspaceSlug, repoSlug, payload); } /** * @deprecated Use client.repositories.deleteRepository() instead */ async deleteRepository(workspaceSlug, repoSlug) { this.logger.debug('Using deprecated deleteRepository method, consider using client.repositories.deleteRepository()'); return this.repositories.deleteRepository(workspaceSlug, repoSlug); } /** * @deprecated Use client.branches.getBranches() instead */ async getBranches(workspaceSlug, repoSlug) { this.logger.debug('Using deprecated getBranches method, consider using client.branches.getBranches()'); return this.branches.getBranches(workspaceSlug, repoSlug); } /** * @deprecated Use client.branches.getAllBranches() instead */ async getAllBranches(workspaceSlug, repoSlug) { this.logger.debug('Using deprecated getAllBranches method, consider using client.branches.getAllBranches()'); return this.branches.getAllBranches(workspaceSlug, repoSlug); } /** * @deprecated Use client.branches.getBranch() instead */ async getBranch(workspaceSlug, repoSlug, branchName) { this.logger.debug('Using deprecated getBranch method, consider using client.branches.getBranch()'); return this.branches.getBranch(workspaceSlug, repoSlug, branchName); } /** * @deprecated Use client.branches.createBranch() instead */ async createBranch(workspaceSlug, repoSlug, payload) { this.logger.debug('Using deprecated createBranch method, consider using client.branches.createBranch()'); return this.branches.createBranch(workspaceSlug, repoSlug, payload); } /** * @deprecated Use client.branches.deleteBranch() instead */ async deleteBranch(workspaceSlug, repoSlug, branchName) { this.logger.debug('Using deprecated deleteBranch method, consider using client.branches.deleteBranch()'); return this.branches.deleteBranch(workspaceSlug, repoSlug, branchName); } /** * @deprecated Use client.branches.getBranchingModel() instead */ async getBranchingModel(workspaceSlug, repoSlug) { this.logger.debug('Using deprecated getBranchingModel method, consider using client.branches.getBranchingModel()'); return this.branches.getBranchingModel(workspaceSlug, repoSlug); } /** * @deprecated Use client.branches.getBranchPermissions() instead */ async getBranchPermissions(workspaceSlug, repoSlug, params) { this.logger.debug('Using deprecated getBranchPermissions method, consider using client.branches.getBranchPermissions()'); return this.branches.getBranchPermissions(workspaceSlug, repoSlug, params); } /** * @deprecated Use client.branches.getAllBranchPermissions() instead */ async getAllBranchPermissions(workspaceSlug, repoSlug, params) { this.logger.debug('Using deprecated getAllBranchPermissions method, consider using client.branches.getAllBranchPermissions()'); return this.branches.getAllBranchPermissions(workspaceSlug, repoSlug, params); } /** * @deprecated Use client.branches.getDefaultReviewers() instead */ async getDefaultReviewers(workspaceSlug, repoSlug, params) { this.logger.debug('Using deprecated getDefaultReviewers method, consider using client.branches.getDefaultReviewers()'); return this.branches.getDefaultReviewers(workspaceSlug, repoSlug, params); } /** * @deprecated Use client.branches.getAllDefaultReviewers() instead */ async getAllDefaultReviewers(workspaceSlug, repoSlug, params) { this.logger.debug('Using deprecated getAllDefaultReviewers method, consider using client.branches.getAllDefaultReviewers()'); return this.branches.getAllDefaultReviewers(workspaceSlug, repoSlug, params); } // ============================================================================= // PULL REQUEST BACKWARD COMPATIBILITY METHODS // ============================================================================= /** * @deprecated Use client.pullRequests.getPullRequests() instead */ async getPullRequests(workspaceSlug, repoSlug, params) { return this.pullRequests.getPullRequests(workspaceSlug, repoSlug, params); } /** * @deprecated Use client.pullRequests.getAllPullRequests() instead */ async getAllPullRequests(workspaceSlug, repoSlug, params) { return this.pullRequests.getAllPullRequests(workspaceSlug, repoSlug, params); } /** * @deprecated Use client.pullRequests.getPullRequest() instead */ async getPullRequest(workspaceSlug, repoSlug, pullRequestId) { return this.pullRequests.getPullRequest(workspaceSlug, repoSlug, pullRequestId); } /** * @deprecated Use client.pullRequests.createPullRequest() instead */ async createPullRequest(workspaceSlug, repoSlug, payload) { return this.pullRequests.createPullRequest(workspaceSlug, repoSlug, payload); } /** * @deprecated Use client.pullRequests.updatePullRequest() instead */ async updatePullRequest(workspaceSlug, repoSlug, pullRequestId, payload) { return this.pullRequests.updatePullRequest(workspaceSlug, repoSlug, pullRequestId, payload); } /** * @deprecated Use client.pullRequests.approvePullRequest() instead */ async approvePullRequest(workspaceSlug, repoSlug, pullRequestId) { return this.pullRequests.approvePullRequest(workspaceSlug, repoSlug, pullRequestId); } /** * @deprecated Use client.pullRequests.unapprovePullRequest() instead */ async unapprovePullRequest(workspaceSlug, repoSlug, pullRequestId) { return this.pullRequests.unapprovePullRequest(workspaceSlug, repoSlug, pullRequestId); } /** * @deprecated Use client.pullRequests.mergePullRequest() instead */ async mergePullRequest(workspaceSlug, repoSlug, pullRequestId, payload) { return this.pullRequests.mergePullRequest(workspaceSlug, repoSlug, pullRequestId, payload); } /** * @deprecated Use client.pullRequests.declinePullRequest() instead */ async declinePullRequest(workspaceSlug, repoSlug, pullRequestId) { return this.pullRequests.declinePullRequest(workspaceSlug, repoSlug, pullRequestId); } /** * @deprecated Use client.pullRequests.addComment() instead */ async addComment(workspaceSlug, repoSlug, pullRequestId, payload) { return this.pullRequests.addComment(workspaceSlug, repoSlug, pullRequestId, payload); } /** * @deprecated Use client.pullRequests.getComments() instead */ async getComments(workspaceSlug, repoSlug, pullRequestId) { return this.pullRequests.getComments(workspaceSlug, repoSlug, pullRequestId); } /** * @deprecated Use client.pullRequests.getAllComments() instead */ async getAllComments(workspaceSlug, repoSlug, pullRequestId) { return this.pullRequests.getAllComments(workspaceSlug, repoSlug, pullRequestId); } // ============================================================================= // COMMIT BACKWARD COMPATIBILITY METHODS // ============================================================================= /** * @deprecated Use client.commits.getCommits() instead */ async getCommits(workspaceSlug, repoSlug, params) { return this.commits.getCommits(workspaceSlug, repoSlug, params); } /** * @deprecated Use client.commits.getAllCommits() instead */ async getAllCommits(workspaceSlug, repoSlug, params) { return this.commits.getAllCommits(workspaceSlug, repoSlug, params); } /** * @deprecated Use client.commits.getCommit() instead */ async getCommit(workspaceSlug, repoSlug, commitHash) { return this.commits.getCommit(workspaceSlug, repoSlug, commitHash); } /** * @deprecated Use client.commits.getCommitDiff() instead */ async getCommitDiff(workspaceSlug, repoSlug, commitHash, params) { return this.commits.getCommitDiff(workspaceSlug, repoSlug, commitHash, params); } /** * @deprecated Use client.commits.getCommitPatch() instead */ async getCommitPatch(workspaceSlug, repoSlug, commitHash) { return this.commits.getCommitPatch(workspaceSlug, repoSlug, commitHash); } // ============================================================================= // ISSUE BACKWARD COMPATIBILITY METHODS // ============================================================================= /** * @deprecated Use client.issues.getIssues() instead */ async getIssues(workspaceSlug, repoSlug, params) { return this.issues.getIssues(workspaceSlug, repoSlug, params); } /** * @deprecated Use client.issues.getAllIssues() instead */ async getAllIssues(workspaceSlug, repoSlug, params) { return this.issues.getAllIssues(workspaceSlug, repoSlug, params); } /** * @deprecated Use client.issues.getIssue() instead */ async getIssue(workspaceSlug, repoSlug, issueId) { return this.issues.getIssue(workspaceSlug, repoSlug, issueId); } /** * @deprecated Use client.issues.createIssue() instead */ async createIssue(workspaceSlug, repoSlug, payload) { return this.issues.createIssue(workspaceSlug, repoSlug, payload); } /** * @deprecated Use client.issues.updateIssue() instead */ async updateIssue(workspaceSlug, repoSlug, issueId, payload) { return this.issues.updateIssue(workspaceSlug, repoSlug, issueId, payload); } /** * @deprecated Use client.issues.deleteIssue() instead */ async deleteIssue(workspaceSlug, repoSlug, issueId) { return this.issues.deleteIssue(workspaceSlug, repoSlug, issueId); } /** * @deprecated Use client.issues.getIssueComments() instead */ async getIssueComments(workspaceSlug, repoSlug, issueId, params) { return this.issues.getIssueComments(workspaceSlug, repoSlug, issueId, params); } /** * @deprecated Use client.issues.addIssueComment() instead */ async addIssueComment(workspaceSlug, repoSlug, issueId, content) { return this.issues.addIssueComment(workspaceSlug, repoSlug, issueId, content); } /** * @deprecated Use client.issues.getComponents() instead */ async getComponents(workspaceSlug, repoSlug) { return this.issues.getComponents(workspaceSlug, repoSlug); } /** * @deprecated Use client.issues.getMilestones() instead */ async getMilestones(workspaceSlug, repoSlug, params) { return this.issues.getMilestones(workspaceSlug, repoSlug, params); } /** * @deprecated Use client.issues.getVersions() instead */ async getVersions(workspaceSlug, repoSlug, params) { return this.issues.getVersions(workspaceSlug, repoSlug, params); } /** * @deprecated Use client.issues.assignIssue() instead */ async assignIssue(workspaceSlug, repoSlug, issueId, assignee) { return this.issues.assignIssue(workspaceSlug, repoSlug, issueId, assignee); } /** * @deprecated Use client.issues.voteIssue() instead */ async voteIssue(workspaceSlug, repoSlug, issueId) { return this.issues.voteIssue(workspaceSlug, repoSlug, issueId); } /** * @deprecated Use client.issues.watchIssue() instead */ async watchIssue(workspaceSlug, repoSlug, issueId, watch = true) { return this.issues.watchIssue(workspaceSlug, repoSlug, issueId, watch); } // Add placeholder methods for other issue operations referenced in tools async searchIssues(workspaceSlug, repoSlug, query, params) { // This method doesn't exist in our current issue client, but tools expect it // We can implement this in the issue client later or return an error throw new Error('searchIssues method not yet implemented in the new architecture'); } async getIssueChanges(workspaceSlug, repoSlug, issueId) { throw new Error('getIssueChanges method not yet implemented in the new architecture'); } async getIssueWatchers(workspaceSlug, repoSlug, issueId) { throw new Error('getIssueWatchers method not yet implemented in the new architecture'); } async getIssueComment(workspaceSlug, repoSlug, issueId, commentId) { throw new Error('getIssueComment method not yet implemented in the new architecture'); } async updateIssueComment(workspaceSlug, repoSlug, issueId, commentId, content) { throw new Error('updateIssueComment method not yet implemented in the new architecture'); } async deleteIssueComment(workspaceSlug, repoSlug, issueId, commentId) { throw new Error('deleteIssueComment method not yet implemented in the new architecture'); } async getComponent(workspaceSlug, repoSlug, componentId) { throw new Error('getComponent method not yet implemented in the new architecture'); } async getMilestone(workspaceSlug, repoSlug, milestoneId) { throw new Error('getMilestone method not yet implemented in the new architecture'); } async getVersion(workspaceSlug, repoSlug, versionId) { throw new Error('getVersion method not yet implemented in the new architecture'); } // ============================================================================= // HEALTH CHECK // ============================================================================= /** * Performs a health check to verify API connectivity and authentication. * * This method tests both authentication status and basic API connectivity * by making a simple API call. Use this to verify the client is properly * configured and can communicate with Bitbucket. * * @returns Promise resolving to health status including authentication state */ async healthCheck() { try { // Test authentication by attempting to list workspaces await this.workspaces.getWorkspaces(); return { status: 'ok', isAuthenticated: true, timestamp: Date.now(), }; } catch (error) { this.logger.error('Health check failed', error); return { status: 'error', isAuthenticated: false, timestamp: Date.now(), }; } } } //# sourceMappingURL=bitbucket-client.js.map