| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845 |
- /**
- * Gogs API Client
- * Provides methods to interact with a Gogs server REST API
- */
- import axios, { AxiosInstance } from 'axios';
- import type {
- GogsUser,
- GogsRepository,
- GogsSearchResponse,
- GogsFileContent,
- GogsBranch,
- GogsCommit,
- GogsConfig,
- GogsIssue,
- GogsIssueComment,
- GogsLabel,
- GogsMilestone,
- GogsOrganization,
- GogsTeam,
- GogsTree,
- GogsRelease,
- GogsCollaborator,
- GogsEmail,
- GogsPublicKey,
- GogsWebhook,
- GogsWebhookEvent,
- GogsWebhookType,
- GogsWebhookConfig,
- GogsFollower,
- } from './types.js';
- export class GogsClient {
- private client: AxiosInstance;
- private serverUrl: string;
- constructor(config: GogsConfig) {
- this.serverUrl = config.serverUrl.replace(/\/$/, '');
- this.client = axios.create({
- baseURL: `${this.serverUrl}/api/v1`,
- headers: {
- 'Content-Type': 'application/json',
- ...(config.accessToken && { Authorization: `token ${config.accessToken}` }),
- },
- });
- }
- /**
- * Get information about the authenticated user
- */
- async getCurrentUser(): Promise<GogsUser> {
- const response = await this.client.get<GogsUser>('/user');
- return response.data;
- }
- /**
- * Get information about a specific user
- */
- async getUser(username: string): Promise<GogsUser> {
- const response = await this.client.get<GogsUser>(`/users/${username}`);
- return response.data;
- }
- /**
- * Search for users
- */
- async searchUsers(query: string, limit: number = 10): Promise<GogsUser[]> {
- const response = await this.client.get<GogsSearchResponse<GogsUser>>('/users/search', {
- params: { q: query, limit },
- });
- return response.data.data;
- }
- /**
- * List repositories for the authenticated user
- */
- async listMyRepositories(): Promise<GogsRepository[]> {
- const response = await this.client.get<GogsRepository[]>('/user/repos');
- return response.data;
- }
- /**
- * List repositories for a specific user
- */
- async listUserRepositories(username: string): Promise<GogsRepository[]> {
- const response = await this.client.get<GogsRepository[]>(`/users/${username}/repos`);
- return response.data;
- }
- /**
- * Search for repositories
- */
- async searchRepositories(
- query: string,
- options?: { uid?: number; limit?: number; page?: number }
- ): Promise<GogsRepository[]> {
- const response = await this.client.get<GogsSearchResponse<GogsRepository>>('/repos/search', {
- params: {
- q: query,
- uid: options?.uid || 0,
- limit: options?.limit || 10,
- page: options?.page || 1,
- },
- });
- return response.data.data;
- }
- /**
- * Get information about a specific repository
- */
- async getRepository(owner: string, repo: string): Promise<GogsRepository> {
- const response = await this.client.get<GogsRepository>(`/repos/${owner}/${repo}`);
- return response.data;
- }
- /**
- * Create a new repository
- */
- async createRepository(data: {
- name: string;
- description?: string;
- private?: boolean;
- auto_init?: boolean;
- gitignores?: string;
- license?: string;
- readme?: string;
- }): Promise<GogsRepository> {
- const response = await this.client.post<GogsRepository>('/user/repos', data);
- return response.data;
- }
- /**
- * Delete a repository
- */
- async deleteRepository(owner: string, repo: string): Promise<void> {
- await this.client.delete(`/repos/${owner}/${repo}`);
- }
- /**
- * Get file or directory contents
- */
- async getContents(
- owner: string,
- repo: string,
- path: string,
- ref?: string
- ): Promise<GogsFileContent | GogsFileContent[]> {
- const response = await this.client.get<GogsFileContent | GogsFileContent[]>(
- `/repos/${owner}/${repo}/contents/${path}`,
- {
- params: ref ? { ref } : undefined,
- }
- );
- return response.data;
- }
- /**
- * Get raw file content
- */
- async getRawContent(owner: string, repo: string, ref: string, path: string): Promise<string> {
- const response = await this.client.get<string>(
- `/repos/${owner}/${repo}/raw/${ref}/${path}`,
- {
- responseType: 'text',
- }
- );
- return response.data;
- }
- /**
- * List branches in a repository
- */
- async listBranches(owner: string, repo: string): Promise<GogsBranch[]> {
- const response = await this.client.get<GogsBranch[]>(`/repos/${owner}/${repo}/branches`);
- return response.data;
- }
- /**
- * Get commits from a repository
- */
- async getCommits(
- owner: string,
- repo: string,
- options?: { sha?: string; page?: number }
- ): Promise<GogsCommit[]> {
- const response = await this.client.get<GogsCommit[]>(`/repos/${owner}/${repo}/commits`, {
- params: {
- sha: options?.sha,
- page: options?.page || 1,
- },
- });
- return response.data;
- }
- /**
- * Get a git tree by SHA
- */
- async getTree(owner: string, repo: string, sha: string): Promise<GogsTree> {
- const response = await this.client.get<GogsTree>(`/repos/${owner}/${repo}/git/trees/${sha}`);
- return response.data;
- }
- /**
- * List issues in a repository
- */
- async listIssues(
- owner: string,
- repo: string,
- options?: {
- state?: 'open' | 'closed' | 'all';
- labels?: string;
- page?: number;
- per_page?: number;
- }
- ): Promise<GogsIssue[]> {
- const response = await this.client.get<GogsIssue[]>(`/repos/${owner}/${repo}/issues`, {
- params: {
- state: options?.state || 'open',
- labels: options?.labels,
- page: options?.page || 1,
- per_page: options?.per_page || 30,
- },
- });
- return response.data;
- }
- /**
- * Get a specific issue
- */
- async getIssue(owner: string, repo: string, number: number): Promise<GogsIssue> {
- const response = await this.client.get<GogsIssue>(`/repos/${owner}/${repo}/issues/${number}`);
- return response.data;
- }
- /**
- * Create a new issue
- */
- async createIssue(
- owner: string,
- repo: string,
- data: {
- title: string;
- body?: string;
- assignee?: string;
- milestone?: number;
- labels?: number[];
- }
- ): Promise<GogsIssue> {
- const response = await this.client.post<GogsIssue>(
- `/repos/${owner}/${repo}/issues`,
- data
- );
- return response.data;
- }
- /**
- * Update an existing issue
- */
- async updateIssue(
- owner: string,
- repo: string,
- number: number,
- data: {
- title?: string;
- body?: string;
- assignee?: string;
- milestone?: number;
- state?: 'open' | 'closed';
- labels?: number[];
- }
- ): Promise<GogsIssue> {
- const response = await this.client.patch<GogsIssue>(
- `/repos/${owner}/${repo}/issues/${number}`,
- data
- );
- return response.data;
- }
- /**
- * List comments on an issue
- */
- async listIssueComments(
- owner: string,
- repo: string,
- number: number
- ): Promise<GogsIssueComment[]> {
- const response = await this.client.get<GogsIssueComment[]>(
- `/repos/${owner}/${repo}/issues/${number}/comments`
- );
- return response.data;
- }
- /**
- * Create a comment on an issue
- */
- async createIssueComment(
- owner: string,
- repo: string,
- number: number,
- body: string
- ): Promise<GogsIssueComment> {
- const response = await this.client.post<GogsIssueComment>(
- `/repos/${owner}/${repo}/issues/${number}/comments`,
- { body }
- );
- return response.data;
- }
- /**
- * Edit a comment on an issue
- */
- async updateIssueComment(
- owner: string,
- repo: string,
- commentId: number,
- body: string
- ): Promise<GogsIssueComment> {
- const response = await this.client.patch<GogsIssueComment>(
- `/repos/${owner}/${repo}/issues/comments/${commentId}`,
- { body }
- );
- return response.data;
- }
- /**
- * List all labels in a repository
- */
- async listLabels(owner: string, repo: string): Promise<GogsLabel[]> {
- const response = await this.client.get<GogsLabel[]>(`/repos/${owner}/${repo}/labels`);
- return response.data;
- }
- /**
- * Get a specific label by ID
- */
- async getLabel(owner: string, repo: string, labelId: number): Promise<GogsLabel> {
- const response = await this.client.get<GogsLabel>(`/repos/${owner}/${repo}/labels/${labelId}`);
- return response.data;
- }
- /**
- * Create a new label
- */
- async createLabel(
- owner: string,
- repo: string,
- data: {
- name: string;
- color: string;
- }
- ): Promise<GogsLabel> {
- const response = await this.client.post<GogsLabel>(
- `/repos/${owner}/${repo}/labels`,
- data
- );
- return response.data;
- }
- /**
- * Update an existing label
- */
- async updateLabel(
- owner: string,
- repo: string,
- labelId: number,
- data: {
- name?: string;
- color?: string;
- }
- ): Promise<GogsLabel> {
- const response = await this.client.patch<GogsLabel>(
- `/repos/${owner}/${repo}/labels/${labelId}`,
- data
- );
- return response.data;
- }
- /**
- * Delete a label
- */
- async deleteLabel(owner: string, repo: string, labelId: number): Promise<void> {
- await this.client.delete(`/repos/${owner}/${repo}/labels/${labelId}`);
- }
- /**
- * List labels on a specific issue
- */
- async listIssueLabels(owner: string, repo: string, issueNumber: number): Promise<GogsLabel[]> {
- const response = await this.client.get<GogsLabel[]>(
- `/repos/${owner}/${repo}/issues/${issueNumber}/labels`
- );
- return response.data;
- }
- /**
- * Add labels to an issue
- */
- async addIssueLabels(
- owner: string,
- repo: string,
- issueNumber: number,
- labelIds: number[]
- ): Promise<GogsLabel[]> {
- const response = await this.client.post<GogsLabel[]>(
- `/repos/${owner}/${repo}/issues/${issueNumber}/labels`,
- { labels: labelIds }
- );
- return response.data;
- }
- /**
- * Remove a label from an issue
- */
- async removeIssueLabel(
- owner: string,
- repo: string,
- issueNumber: number,
- labelId: number
- ): Promise<void> {
- await this.client.delete(`/repos/${owner}/${repo}/issues/${issueNumber}/labels/${labelId}`);
- }
- /**
- * Replace all labels on an issue
- */
- async replaceIssueLabels(
- owner: string,
- repo: string,
- issueNumber: number,
- labelIds: number[]
- ): Promise<GogsLabel[]> {
- const response = await this.client.put<GogsLabel[]>(
- `/repos/${owner}/${repo}/issues/${issueNumber}/labels`,
- { labels: labelIds }
- );
- return response.data;
- }
- /**
- * Remove all labels from an issue
- */
- async removeAllIssueLabels(
- owner: string,
- repo: string,
- issueNumber: number
- ): Promise<void> {
- await this.client.delete(`/repos/${owner}/${repo}/issues/${issueNumber}/labels`);
- }
- /**
- * List all milestones in a repository
- */
- async listMilestones(owner: string, repo: string): Promise<GogsMilestone[]> {
- const response = await this.client.get<GogsMilestone[]>(`/repos/${owner}/${repo}/milestones`);
- return response.data;
- }
- /**
- * Get a specific milestone by ID
- */
- async getMilestone(owner: string, repo: string, milestoneId: number): Promise<GogsMilestone> {
- const response = await this.client.get<GogsMilestone>(`/repos/${owner}/${repo}/milestones/${milestoneId}`);
- return response.data;
- }
- /**
- * Create a new milestone
- */
- async createMilestone(
- owner: string,
- repo: string,
- data: {
- title: string;
- description?: string;
- due_on?: string;
- }
- ): Promise<GogsMilestone> {
- const response = await this.client.post<GogsMilestone>(
- `/repos/${owner}/${repo}/milestones`,
- data
- );
- return response.data;
- }
- /**
- * Update an existing milestone
- */
- async updateMilestone(
- owner: string,
- repo: string,
- milestoneId: number,
- data: {
- title?: string;
- description?: string;
- due_on?: string;
- state?: 'open' | 'closed';
- }
- ): Promise<GogsMilestone> {
- const response = await this.client.patch<GogsMilestone>(
- `/repos/${owner}/${repo}/milestones/${milestoneId}`,
- data
- );
- return response.data;
- }
- /**
- * Delete a milestone
- */
- async deleteMilestone(owner: string, repo: string, milestoneId: number): Promise<void> {
- await this.client.delete(`/repos/${owner}/${repo}/milestones/${milestoneId}`);
- }
- /**
- * List organizations for the authenticated user
- */
- async listUserOrganizations(): Promise<GogsOrganization[]> {
- const response = await this.client.get<GogsOrganization[]>('/user/orgs');
- return response.data;
- }
- /**
- * Create a new organization
- */
- async createOrganization(data: {
- username: string;
- full_name?: string;
- description?: string;
- website?: string;
- location?: string;
- }): Promise<GogsOrganization> {
- const response = await this.client.post<GogsOrganization>('/user/orgs', data);
- return response.data;
- }
- /**
- * List public organizations for a specific user
- */
- async listPublicOrganizations(username: string): Promise<GogsOrganization[]> {
- const response = await this.client.get<GogsOrganization[]>(`/users/${username}/orgs`);
- return response.data;
- }
- /**
- * Get information about a specific organization
- */
- async getOrganization(orgname: string): Promise<GogsOrganization> {
- const response = await this.client.get<GogsOrganization>(`/orgs/${orgname}`);
- return response.data;
- }
- /**
- * Update an organization
- */
- async updateOrganization(
- orgname: string,
- data: {
- full_name?: string;
- description?: string;
- website?: string;
- location?: string;
- }
- ): Promise<GogsOrganization> {
- const response = await this.client.patch<GogsOrganization>(`/orgs/${orgname}`, data);
- return response.data;
- }
- /**
- * Add or update organization membership
- */
- async addOrganizationMember(
- orgname: string,
- username: string,
- role: 'admin' | 'member'
- ): Promise<void> {
- await this.client.put(`/orgs/${orgname}/memberships/${username}`, { role });
- }
- /**
- * List teams in an organization
- */
- async listOrganizationTeams(orgname: string): Promise<GogsTeam[]> {
- const response = await this.client.get<GogsTeam[]>(`/orgs/${orgname}/teams`);
- return response.data;
- }
- /**
- * Create a new team in an organization
- */
- async createTeam(
- orgname: string,
- data: {
- name: string;
- description?: string;
- permission?: 'read' | 'write' | 'admin';
- }
- ): Promise<GogsTeam> {
- const response = await this.client.post<GogsTeam>(
- `/admin/orgs/${orgname}/teams`,
- data
- );
- return response.data;
- }
- /**
- * Get a specific team by ID
- */
- async getTeam(teamId: number): Promise<GogsTeam> {
- const response = await this.client.get<GogsTeam>(`/teams/${teamId}`);
- return response.data;
- }
- /**
- * Add a user to a team
- */
- async addTeamMember(teamId: number, username: string): Promise<void> {
- await this.client.put(`/admin/teams/${teamId}/members/${username}`);
- }
- /**
- * Remove a user from a team
- */
- async removeTeamMember(teamId: number, username: string): Promise<void> {
- await this.client.delete(`/admin/teams/${teamId}/members/${username}`);
- }
- /**
- * List releases for a repository
- */
- async listReleases(owner: string, repo: string): Promise<GogsRelease[]> {
- const response = await this.client.get<GogsRelease[]>(`/repos/${owner}/${repo}/releases`);
- return response.data;
- }
- /**
- * List collaborators for a repository
- */
- async listCollaborators(owner: string, repo: string): Promise<GogsCollaborator[]> {
- const response = await this.client.get<GogsCollaborator[]>(
- `/repos/${owner}/${repo}/collaborators`
- );
- return response.data;
- }
- /**
- * Check if a user is a collaborator
- */
- async checkCollaborator(owner: string, repo: string, username: string): Promise<boolean> {
- try {
- await this.client.get(`/repos/${owner}/${repo}/collaborators/${username}`);
- return true;
- } catch (error) {
- if (axios.isAxiosError(error) && error.response?.status === 404) {
- return false;
- }
- throw error;
- }
- }
- /**
- * Add a collaborator to a repository
- */
- async addCollaborator(
- owner: string,
- repo: string,
- username: string,
- permission?: 'read' | 'write' | 'admin'
- ): Promise<void> {
- await this.client.put(`/repos/${owner}/${repo}/collaborators/${username}`, {
- permission: permission || 'write',
- });
- }
- /**
- * Remove a collaborator from a repository
- */
- async removeCollaborator(owner: string, repo: string, username: string): Promise<void> {
- await this.client.delete(`/repos/${owner}/${repo}/collaborators/${username}`);
- }
- /**
- * List email addresses for the authenticated user
- */
- async listUserEmails(): Promise<GogsEmail[]> {
- const response = await this.client.get<GogsEmail[]>('/user/emails');
- return response.data;
- }
- /**
- * Add email address(es) to the authenticated user's account
- */
- async addUserEmails(emails: string[]): Promise<GogsEmail[]> {
- const response = await this.client.post<GogsEmail[]>('/user/emails', { emails });
- return response.data;
- }
- /**
- * Delete email address(es) from the authenticated user's account
- */
- async deleteUserEmails(emails: string[]): Promise<void> {
- await this.client.delete('/user/emails', { data: { emails } });
- }
- /**
- * List public keys for a specific user
- */
- async listUserKeys(username: string): Promise<GogsPublicKey[]> {
- const response = await this.client.get<GogsPublicKey[]>(`/users/${username}/keys`);
- return response.data;
- }
- /**
- * List public keys for the authenticated user
- */
- async listMyKeys(): Promise<GogsPublicKey[]> {
- const response = await this.client.get<GogsPublicKey[]>('/user/keys');
- return response.data;
- }
- /**
- * Get a single public key by ID
- */
- async getPublicKey(keyId: number): Promise<GogsPublicKey> {
- const response = await this.client.get<GogsPublicKey>(`/user/keys/${keyId}`);
- return response.data;
- }
- /**
- * Create a new public key for the authenticated user
- */
- async createPublicKey(data: {
- title: string;
- key: string;
- }): Promise<GogsPublicKey> {
- const response = await this.client.post<GogsPublicKey>('/user/keys', data);
- return response.data;
- }
- /**
- * Delete a public key by ID
- */
- async deletePublicKey(keyId: number): Promise<void> {
- await this.client.delete(`/user/keys/${keyId}`);
- }
- /**
- * List webhooks for a repository
- */
- async listHooks(owner: string, repo: string): Promise<GogsWebhook[]> {
- const response = await this.client.get<GogsWebhook[]>(`/repos/${owner}/${repo}/hooks`);
- return response.data;
- }
- /**
- * Create a new webhook for a repository
- */
- async createHook(
- owner: string,
- repo: string,
- data: {
- type: GogsWebhookType;
- config: GogsWebhookConfig;
- events?: GogsWebhookEvent[];
- active?: boolean;
- }
- ): Promise<GogsWebhook> {
- const response = await this.client.post<GogsWebhook>(
- `/repos/${owner}/${repo}/hooks`,
- data
- );
- return response.data;
- }
- /**
- * Update an existing webhook
- */
- async updateHook(
- owner: string,
- repo: string,
- hookId: number,
- data: {
- config: GogsWebhookConfig;
- events?: GogsWebhookEvent[];
- active?: boolean;
- }
- ): Promise<GogsWebhook> {
- const response = await this.client.patch<GogsWebhook>(
- `/repos/${owner}/${repo}/hooks/${hookId}`,
- data
- );
- return response.data;
- }
- /**
- * Delete a webhook from a repository
- */
- async deleteHook(owner: string, repo: string, hookId: number): Promise<void> {
- await this.client.delete(`/repos/${owner}/${repo}/hooks/${hookId}`);
- }
- /**
- * List followers of a user
- */
- async listFollowers(username: string): Promise<GogsFollower[]> {
- const response = await this.client.get<GogsFollower[]>(`/users/${username}/followers`);
- return response.data;
- }
- /**
- * List users that a user is following
- */
- async listFollowing(username: string): Promise<GogsFollower[]> {
- const response = await this.client.get<GogsFollower[]>(`/users/${username}/following`);
- return response.data;
- }
- /**
- * Check if the authenticated user is following a target user
- */
- async checkFollowing(username: string): Promise<boolean> {
- try {
- await this.client.get(`/user/following/${username}`);
- return true;
- } catch (error) {
- if (axios.isAxiosError(error) && error.response?.status === 404) {
- return false;
- }
- throw error;
- }
- }
- /**
- * Follow a user (authenticated user follows the target user)
- */
- async followUser(username: string): Promise<void> {
- await this.client.put(`/user/following/${username}`);
- }
- /**
- * Unfollow a user (authenticated user unfollows the target user)
- */
- async unfollowUser(username: string): Promise<void> {
- await this.client.delete(`/user/following/${username}`);
- }
- }
|