@tiberriver256/mcp-server-azure-devops
Version:
Azure DevOps reference server for the Model Context Protocol (MCP)
91 lines • 4.23 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.manageWorkItemLink = manageWorkItemLink;
const WorkItemTrackingInterfaces_1 = require("azure-devops-node-api/interfaces/WorkItemTrackingInterfaces");
const errors_1 = require("../../../shared/errors");
/**
* Manage (add, remove, or update) a link between two work items
*
* @param connection The Azure DevOps WebApi connection
* @param projectId The ID or name of the project
* @param options Options for managing the work item link
* @returns The updated source work item
* @throws {AzureDevOpsResourceNotFoundError} If either work item is not found
*/
async function manageWorkItemLink(connection, projectId, options) {
try {
const { sourceWorkItemId, targetWorkItemId, operation, relationType, newRelationType, comment, } = options;
// Input validation
if (!sourceWorkItemId) {
throw new Error('Source work item ID is required');
}
if (!targetWorkItemId) {
throw new Error('Target work item ID is required');
}
if (!relationType) {
throw new Error('Relation type is required');
}
if (operation === 'update' && !newRelationType) {
throw new Error('New relation type is required for update operation');
}
const witApi = await connection.getWorkItemTrackingApi();
// Create the JSON patch document
const document = [];
// Construct the relationship URL
const relationshipUrl = `${connection.serverUrl}/_apis/wit/workItems/${targetWorkItemId}`;
let relationIndex = -1;
if (operation === 'remove' || operation === 'update') {
const sourceWorkItem = await witApi.getWorkItem(sourceWorkItemId, undefined, undefined, WorkItemTrackingInterfaces_1.WorkItemExpand.Relations);
if (!sourceWorkItem) {
throw new errors_1.AzureDevOpsResourceNotFoundError(`Work item '${sourceWorkItemId}' not found`);
}
const relations = sourceWorkItem.relations || [];
const targetSuffix = `/_apis/wit/workItems/${targetWorkItemId}`.toLowerCase();
relationIndex = relations.findIndex((rel) => rel.rel?.toLowerCase() === relationType.toLowerCase() &&
rel.url?.toLowerCase().endsWith(targetSuffix));
if (relationIndex === -1) {
throw new errors_1.AzureDevOpsResourceNotFoundError(`Relation of type '${relationType}' to target work item '${targetWorkItemId}' not found on source work item '${sourceWorkItemId}'`);
}
}
if (operation === 'add' || operation === 'update') {
// For 'update', we'll first remove the old link, then add the new one
if (operation === 'update') {
document.push({
op: 'remove',
path: `/relations/${relationIndex}`,
});
}
// Add the new relationship
document.push({
op: 'add',
path: '/relations/-',
value: {
rel: operation === 'update' ? newRelationType : relationType,
url: relationshipUrl,
...(comment ? { attributes: { comment } } : {}),
},
});
}
else if (operation === 'remove') {
// Remove the relationship
document.push({
op: 'remove',
path: `/relations/${relationIndex}`,
});
}
// Update the work item with the new relationship
const updatedWorkItem = await witApi.updateWorkItem({}, // customHeaders
document, sourceWorkItemId, projectId);
if (!updatedWorkItem) {
throw new errors_1.AzureDevOpsResourceNotFoundError(`Work item '${sourceWorkItemId}' not found`);
}
return updatedWorkItem;
}
catch (error) {
if (error instanceof errors_1.AzureDevOpsError) {
throw error;
}
throw new Error(`Failed to manage work item link: ${error instanceof Error ? error.message : String(error)}`);
}
}
//# sourceMappingURL=feature.js.map