-
-
Notifications
You must be signed in to change notification settings - Fork 115
Expand file tree
/
Copy pathfeature.ts
More file actions
125 lines (112 loc) · 3.39 KB
/
feature.ts
File metadata and controls
125 lines (112 loc) · 3.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import { WebApi } from 'azure-devops-node-api';
import { TeamContext } from 'azure-devops-node-api/interfaces/CoreInterfaces';
import {
WorkItem,
WorkItemReference,
} from 'azure-devops-node-api/interfaces/WorkItemTrackingInterfaces';
import {
AzureDevOpsError,
AzureDevOpsAuthenticationError,
AzureDevOpsResourceNotFoundError,
} from '../../../shared/errors';
import { ListWorkItemsOptions, WorkItem as WorkItemType } from '../types';
/**
* Constructs the default WIQL query for listing work items
*/
function constructDefaultWiql(projectId: string, teamId?: string): string {
let query = `SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = '${projectId}'`;
if (teamId) {
query += ` AND [System.TeamId] = '${teamId}'`;
}
query += ' ORDER BY [System.Id]';
return query;
}
/**
* List work items in a project
*
* @param connection The Azure DevOps WebApi connection
* @param options Options for listing work items
* @returns List of work items
*/
export async function listWorkItems(
connection: WebApi,
options: ListWorkItemsOptions,
): Promise<WorkItemType[]> {
try {
const witApi = await connection.getWorkItemTrackingApi();
const { projectId, teamId, queryId, wiql } = options;
let workItemRefs: WorkItemReference[] = [];
if (queryId) {
const teamContext: TeamContext = {
project: projectId,
team: teamId,
};
const queryResult = await witApi.queryById(queryId, teamContext);
workItemRefs = queryResult.workItems || [];
} else {
const query = wiql || constructDefaultWiql(projectId, teamId);
const teamContext: TeamContext = {
project: projectId,
team: teamId,
};
const queryResult = await witApi.queryByWiql({ query }, teamContext);
workItemRefs = queryResult.workItems || [];
}
// Apply pagination in memory
const { top = 200, skip } = options;
if (skip !== undefined) {
workItemRefs = workItemRefs.slice(skip);
}
if (top !== undefined) {
workItemRefs = workItemRefs.slice(0, top);
}
const workItemIds = workItemRefs
.map((ref) => ref.id)
.filter((id): id is number => id !== undefined);
if (workItemIds.length === 0) {
return [];
}
const fields = [
'System.Id',
'System.Title',
'System.State',
'System.AssignedTo',
];
const workItems = await witApi.getWorkItems(
workItemIds,
fields,
undefined,
undefined,
);
if (!workItems) {
return [];
}
return workItems.filter((wi): wi is WorkItem => wi !== undefined);
} catch (error) {
if (error instanceof AzureDevOpsError) {
throw error;
}
// Check for specific error types and convert to appropriate Azure DevOps errors
if (error instanceof Error) {
if (
error.message.includes('Authentication') ||
error.message.includes('Unauthorized')
) {
throw new AzureDevOpsAuthenticationError(
`Failed to authenticate: ${error.message}`,
);
}
if (
error.message.includes('not found') ||
error.message.includes('does not exist')
) {
throw new AzureDevOpsResourceNotFoundError(
`Resource not found: ${error.message}`,
);
}
}
throw new AzureDevOpsError(
`Failed to list work items: ${error instanceof Error ? error.message : String(error)}`,
);
}
}