@gohcltech/bitbucket-mcp
Version:
Bitbucket integration for Claude via Model Context Protocol
465 lines • 20.5 kB
JavaScript
/**
* @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