Add GitLab Issue Links API support

This commit is contained in:
Admin
2025-03-18 01:07:12 -07:00
parent 1927a23684
commit 48d33ae990
2 changed files with 210 additions and 1 deletions

175
index.ts
View File

@ -45,6 +45,12 @@ import {
GetIssueSchema,
UpdateIssueSchema,
DeleteIssueSchema,
GitLabIssueLinkSchema,
ListIssueLinksSchema,
GetIssueLinkSchema,
CreateIssueLinkSchema,
DeleteIssueLinkSchema,
CreateNoteSchema,
type GitLabFork,
type GitLabReference,
type GitLabRepository,
@ -57,7 +63,7 @@ import {
type GitLabCommit,
type FileOperation,
type GitLabMergeRequestDiff,
CreateNoteSchema,
type GitLabIssueLink,
} from "./schemas.js";
/**
@ -457,6 +463,121 @@ async function deleteIssue(
await handleGitLabError(response);
}
/**
* List all issue links for a specific issue
* 이슈 관계 목록 조회
*
* @param {string} projectId - The ID or URL-encoded path of the project
* @param {number} issueIid - The internal ID of the project issue
* @returns {Promise<GitLabIssueLink[]>} List of issue links
*/
async function listIssueLinks(
projectId: string,
issueIid: number
): Promise<GitLabIssueLink[]> {
const url = new URL(
`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/issues/${issueIid}/links`
);
const response = await fetch(url.toString(), {
headers: DEFAULT_HEADERS,
});
await handleGitLabError(response);
const data = await response.json();
return z.array(GitLabIssueLinkSchema).parse(data);
}
/**
* Get a specific issue link
* 특정 이슈 관계 조회
*
* @param {string} projectId - The ID or URL-encoded path of the project
* @param {number} issueIid - The internal ID of the project issue
* @param {number} issueLinkId - The ID of the issue link
* @returns {Promise<GitLabIssueLink>} The issue link
*/
async function getIssueLink(
projectId: string,
issueIid: number,
issueLinkId: number
): Promise<GitLabIssueLink> {
const url = new URL(
`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/issues/${issueIid}/links/${issueLinkId}`
);
const response = await fetch(url.toString(), {
headers: DEFAULT_HEADERS,
});
await handleGitLabError(response);
const data = await response.json();
return GitLabIssueLinkSchema.parse(data);
}
/**
* Create an issue link between two issues
* 이슈 관계 생성
*
* @param {string} projectId - The ID or URL-encoded path of the project
* @param {number} issueIid - The internal ID of the project issue
* @param {string} targetProjectId - The ID or URL-encoded path of the target project
* @param {number} targetIssueIid - The internal ID of the target project issue
* @param {string} linkType - The type of the relation (relates_to, blocks, is_blocked_by)
* @returns {Promise<GitLabIssueLink>} The created issue link
*/
async function createIssueLink(
projectId: string,
issueIid: number,
targetProjectId: string,
targetIssueIid: number,
linkType: 'relates_to' | 'blocks' | 'is_blocked_by' = 'relates_to'
): Promise<GitLabIssueLink> {
const url = new URL(
`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/issues/${issueIid}/links`
);
const response = await fetch(url.toString(), {
method: "POST",
headers: DEFAULT_HEADERS,
body: JSON.stringify({
target_project_id: targetProjectId,
target_issue_iid: targetIssueIid,
link_type: linkType
}),
});
await handleGitLabError(response);
const data = await response.json();
return GitLabIssueLinkSchema.parse(data);
}
/**
* Delete an issue link
* 이슈 관계 삭제
*
* @param {string} projectId - The ID or URL-encoded path of the project
* @param {number} issueIid - The internal ID of the project issue
* @param {number} issueLinkId - The ID of the issue link
* @returns {Promise<void>}
*/
async function deleteIssueLink(
projectId: string,
issueIid: number,
issueLinkId: number
): Promise<void> {
const url = new URL(
`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/issues/${issueIid}/links/${issueLinkId}`
);
const response = await fetch(url.toString(), {
method: "DELETE",
headers: DEFAULT_HEADERS,
});
await handleGitLabError(response);
}
/**
* Create a new merge request in a GitLab project
* 병합 요청 생성
@ -1027,6 +1148,26 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
description: "Delete an issue from a GitLab project",
inputSchema: zodToJsonSchema(DeleteIssueSchema),
},
{
name: "list_issue_links",
description: "List all issue links for a specific issue",
inputSchema: zodToJsonSchema(ListIssueLinksSchema),
},
{
name: "get_issue_link",
description: "Get a specific issue link",
inputSchema: zodToJsonSchema(GetIssueLinkSchema),
},
{
name: "create_issue_link",
description: "Create an issue link between two issues",
inputSchema: zodToJsonSchema(CreateIssueLinkSchema),
},
{
name: "delete_issue_link",
description: "Delete an issue link",
inputSchema: zodToJsonSchema(DeleteIssueLinkSchema),
},
],
};
});
@ -1247,6 +1388,38 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
};
}
case "list_issue_links": {
const args = ListIssueLinksSchema.parse(request.params.arguments);
const links = await listIssueLinks(args.project_id, args.issue_iid);
return {
content: [{ type: "text", text: JSON.stringify(links, null, 2) }],
};
}
case "get_issue_link": {
const args = GetIssueLinkSchema.parse(request.params.arguments);
const link = await getIssueLink(args.project_id, args.issue_iid, args.issue_link_id);
return {
content: [{ type: "text", text: JSON.stringify(link, null, 2) }],
};
}
case "create_issue_link": {
const args = CreateIssueLinkSchema.parse(request.params.arguments);
const link = await createIssueLink(args.project_id, args.issue_iid, args.target_project_id, args.target_issue_iid, args.link_type);
return {
content: [{ type: "text", text: JSON.stringify(link, null, 2) }],
};
}
case "delete_issue_link": {
const args = DeleteIssueLinkSchema.parse(request.params.arguments);
await deleteIssueLink(args.project_id, args.issue_iid, args.issue_link_id);
return {
content: [{ type: "text", text: JSON.stringify({ status: "success", message: "Issue link deleted successfully" }, null, 2) }],
};
}
default:
throw new Error(`Unknown tool: ${request.params.name}`);
}