import axios, { AxiosInstance } from 'axios';
export interface BitbucketConfig {
username: string;
appPassword: string;
workspace?: string;
}
export interface Repository {
uuid: string;
slug: string;
name: string;
full_name: string;
description?: string;
is_private: boolean;
created_on: string;
updated_on: string;
size: number;
language: string;
has_issues: boolean;
has_wiki: boolean;
fork_policy: string;
links: {
clone: Array<{ href: string; name: string }>;
html: { href: string };
};
}
export interface PullRequest {
id: number;
title: string;
description?: string;
state: string;
author: {
display_name: string;
uuid: string;
};
source: {
branch: { name: string };
repository: { full_name: string };
};
destination: {
branch: { name: string };
repository: { full_name: string };
};
created_on: string;
updated_on: string;
links: {
html: { href: string };
};
}
export interface Branch {
name: string;
target: {
hash: string;
date: string;
author: {
raw: string;
};
message: string;
};
}
export interface Commit {
hash: string;
date: string;
message: string;
author: {
raw: string;
user?: {
display_name: string;
uuid: string;
};
};
links: {
html: { href: string };
};
}
export class BitbucketClient {
private api: AxiosInstance;
private workspace?: string;
constructor(config: BitbucketConfig) {
this.workspace = config.workspace;
const auth = Buffer.from(`${config.username}:${config.appPassword}`).toString('base64');
this.api = axios.create({
baseURL: 'https://api.bitbucket.org/2.0',
headers: {
'Authorization': `Basic ${auth}`,
'Content-Type': 'application/json',
},
});
}
async listWorkspaces(): Promise<any[]> {
const response = await this.api.get('/workspaces');
return response.data.values;
}
async listRepositories(workspace?: string): Promise<Repository[]> {
const ws = workspace || this.workspace;
if (!ws) {
throw new Error('Workspace is required');
}
const response = await this.api.get(`/repositories/${ws}`);
return response.data.values;
}
async getRepository(workspace: string, repoSlug: string): Promise<Repository> {
const response = await this.api.get(`/repositories/${workspace}/${repoSlug}`);
return response.data;
}
async listBranches(workspace: string, repoSlug: string): Promise<Branch[]> {
const response = await this.api.get(`/repositories/${workspace}/${repoSlug}/refs/branches`);
return response.data.values;
}
async getBranch(workspace: string, repoSlug: string, branchName: string): Promise<Branch> {
const response = await this.api.get(`/repositories/${workspace}/${repoSlug}/refs/branches/${branchName}`);
return response.data;
}
async listPullRequests(workspace: string, repoSlug: string, state?: string): Promise<PullRequest[]> {
const params = state ? { state } : {};
const response = await this.api.get(`/repositories/${workspace}/${repoSlug}/pullrequests`, { params });
return response.data.values;
}
async getPullRequest(workspace: string, repoSlug: string, prId: number): Promise<PullRequest> {
const response = await this.api.get(`/repositories/${workspace}/${repoSlug}/pullrequests/${prId}`);
return response.data;
}
async createPullRequest(
workspace: string,
repoSlug: string,
title: string,
sourceBranch: string,
destinationBranch: string,
description?: string
): Promise<PullRequest> {
const data = {
title,
description,
source: {
branch: { name: sourceBranch }
},
destination: {
branch: { name: destinationBranch }
}
};
const response = await this.api.post(`/repositories/${workspace}/${repoSlug}/pullrequests`, data);
return response.data;
}
async approvePullRequest(workspace: string, repoSlug: string, prId: number): Promise<void> {
await this.api.post(`/repositories/${workspace}/${repoSlug}/pullrequests/${prId}/approve`);
}
async mergePullRequest(workspace: string, repoSlug: string, prId: number): Promise<void> {
await this.api.post(`/repositories/${workspace}/${repoSlug}/pullrequests/${prId}/merge`);
}
async addPullRequestComment(
workspace: string,
repoSlug: string,
prId: number,
content: string
): Promise<void> {
await this.api.post(`/repositories/${workspace}/${repoSlug}/pullrequests/${prId}/comments`, {
content: { raw: content }
});
}
async listCommits(workspace: string, repoSlug: string, branch?: string): Promise<Commit[]> {
const params = branch ? { branch } : {};
const response = await this.api.get(`/repositories/${workspace}/${repoSlug}/commits`, { params });
return response.data.values;
}
async getCommit(workspace: string, repoSlug: string, commitHash: string): Promise<Commit> {
const response = await this.api.get(`/repositories/${workspace}/${repoSlug}/commit/${commitHash}`);
return response.data;
}
async getFileContent(workspace: string, repoSlug: string, path: string, ref?: string): Promise<string> {
const params = ref ? { ref } : {};
const response = await this.api.get(`/repositories/${workspace}/${repoSlug}/src/${ref || 'HEAD'}/${path}`, { params });
return response.data;
}
async searchCode(workspace: string, query: string): Promise<any[]> {
const response = await this.api.get(`/workspaces/${workspace}/search/code`, {
params: { search_query: query }
});
return response.data.values;
}
async compareBranches(
workspace: string,
repoSlug: string,
sourceBranch: string,
destinationBranch: string
): Promise<any> {
const response = await this.api.get(`/repositories/${workspace}/${repoSlug}/diff/${sourceBranch}..${destinationBranch}`);
return response.data;
}
}