@sascha384/tic 0.1.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,11 @@
1
+ export declare function az<T>(args: string[], cwd: string): T;
2
+ export declare function azExec(args: string[], cwd: string): string;
3
+ export interface AzInvokeOptions {
4
+ area: string;
5
+ resource: string;
6
+ httpMethod?: string;
7
+ routeParameters?: string;
8
+ body?: unknown;
9
+ apiVersion?: string;
10
+ }
11
+ export declare function azInvoke<T>(options: AzInvokeOptions, cwd: string): T;
@@ -0,0 +1,58 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import fs from 'node:fs';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+ export function az(args, cwd) {
6
+ const result = execFileSync('az', [...args, '-o', 'json'], {
7
+ cwd,
8
+ encoding: 'utf-8',
9
+ stdio: ['pipe', 'pipe', 'pipe'],
10
+ });
11
+ return JSON.parse(result);
12
+ }
13
+ export function azExec(args, cwd) {
14
+ return execFileSync('az', args, {
15
+ cwd,
16
+ encoding: 'utf-8',
17
+ stdio: ['pipe', 'pipe', 'pipe'],
18
+ });
19
+ }
20
+ export function azInvoke(options, cwd) {
21
+ const args = [
22
+ 'devops',
23
+ 'invoke',
24
+ '--area',
25
+ options.area,
26
+ '--resource',
27
+ options.resource,
28
+ ];
29
+ if (options.httpMethod) {
30
+ args.push('--http-method', options.httpMethod);
31
+ }
32
+ if (options.routeParameters) {
33
+ args.push('--route-parameters', options.routeParameters);
34
+ }
35
+ if (options.apiVersion) {
36
+ args.push('--api-version', options.apiVersion);
37
+ }
38
+ let tmpFile;
39
+ if (options.body) {
40
+ tmpFile = path.join(os.tmpdir(), `tic-az-${Date.now()}.json`);
41
+ fs.writeFileSync(tmpFile, JSON.stringify(options.body));
42
+ args.push('--in-file', tmpFile);
43
+ }
44
+ try {
45
+ const result = execFileSync('az', [...args, '-o', 'json'], {
46
+ cwd,
47
+ encoding: 'utf-8',
48
+ stdio: ['pipe', 'pipe', 'pipe'],
49
+ });
50
+ return JSON.parse(result);
51
+ }
52
+ finally {
53
+ if (tmpFile) {
54
+ fs.unlinkSync(tmpFile);
55
+ }
56
+ }
57
+ }
58
+ //# sourceMappingURL=az.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"az.js","sourceRoot":"","sources":["../../../src/backends/ado/az.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,UAAU,EAAE,CAAI,IAAc,EAAE,GAAW;IAC/C,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE;QACzD,GAAG;QACH,QAAQ,EAAE,OAAO;QACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;KAChC,CAAC,CAAC;IACH,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAM,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,IAAc,EAAE,GAAW;IAChD,OAAO,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE;QAC9B,GAAG;QACH,QAAQ,EAAE,OAAO;QACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;KAChC,CAAC,CAAC;AACL,CAAC;AAWD,MAAM,UAAU,QAAQ,CAAI,OAAwB,EAAE,GAAW;IAC/D,MAAM,IAAI,GAAG;QACX,QAAQ;QACR,QAAQ;QACR,QAAQ;QACR,OAAO,CAAC,IAAI;QACZ,YAAY;QACZ,OAAO,CAAC,QAAQ;KACjB,CAAC;IAEF,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;QACvB,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IACjD,CAAC;IACD,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;QAC5B,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IAC3D,CAAC;IACD,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;QACvB,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IACjD,CAAC;IAED,IAAI,OAA2B,CAAC;IAChC,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,UAAU,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAC9D,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACxD,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAClC,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE;YACzD,GAAG;YACH,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAM,CAAC;IACjC,CAAC;YAAS,CAAC;QACT,IAAI,OAAO,EAAE,CAAC;YACZ,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,28 @@
1
+ import { BaseBackend } from '../types.js';
2
+ import type { BackendCapabilities } from '../types.js';
3
+ import type { WorkItem, NewWorkItem, NewComment, Comment } from '../../types.js';
4
+ export declare class AzureDevOpsBackend extends BaseBackend {
5
+ private cwd;
6
+ private org;
7
+ private project;
8
+ private types;
9
+ constructor(cwd: string);
10
+ getCapabilities(): BackendCapabilities;
11
+ getStatuses(): string[];
12
+ getWorkItemTypes(): string[];
13
+ getIterations(): string[];
14
+ getCurrentIteration(): string;
15
+ setCurrentIteration(_name: string): void;
16
+ private escapeWiql;
17
+ private batchFetchWorkItems;
18
+ listWorkItems(iteration?: string): WorkItem[];
19
+ getWorkItem(id: string): WorkItem;
20
+ createWorkItem(data: NewWorkItem): WorkItem;
21
+ updateWorkItem(id: string, data: Partial<WorkItem>): WorkItem;
22
+ deleteWorkItem(id: string): void;
23
+ addComment(workItemId: string, comment: NewComment): Comment;
24
+ getChildren(id: string): WorkItem[];
25
+ getDependents(id: string): WorkItem[];
26
+ getItemUrl(id: string): string;
27
+ openItem(id: string): void;
28
+ }
@@ -0,0 +1,461 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import { BaseBackend } from '../types.js';
3
+ import { az, azExec, azInvoke } from './az.js';
4
+ import { parseAdoRemote } from './remote.js';
5
+ import { mapWorkItemToWorkItem, mapCommentToComment, mapPriorityToAdo, formatTags, extractParent, extractPredecessors, } from './mappers.js';
6
+ const BATCH_FIELDS = [
7
+ 'System.Id',
8
+ 'System.Title',
9
+ 'System.WorkItemType',
10
+ 'System.State',
11
+ 'System.IterationPath',
12
+ 'Microsoft.VSTS.Common.Priority',
13
+ 'System.AssignedTo',
14
+ 'System.Tags',
15
+ 'System.Description',
16
+ 'System.CreatedDate',
17
+ 'System.ChangedDate',
18
+ ];
19
+ export class AzureDevOpsBackend extends BaseBackend {
20
+ cwd;
21
+ org;
22
+ project;
23
+ types;
24
+ constructor(cwd) {
25
+ super();
26
+ this.cwd = cwd;
27
+ azExec(['account', 'show'], cwd);
28
+ const remote = parseAdoRemote(cwd);
29
+ this.org = remote.org;
30
+ this.project = remote.project;
31
+ this.types = az([
32
+ 'boards',
33
+ 'work-item',
34
+ 'type',
35
+ 'list',
36
+ '--org',
37
+ `https://dev.azure.com/${this.org}`,
38
+ '--project',
39
+ this.project,
40
+ ], cwd);
41
+ }
42
+ getCapabilities() {
43
+ return {
44
+ relationships: true,
45
+ customTypes: false,
46
+ customStatuses: false,
47
+ iterations: true,
48
+ comments: true,
49
+ fields: {
50
+ priority: true,
51
+ assignee: true,
52
+ labels: true,
53
+ parent: true,
54
+ dependsOn: true,
55
+ },
56
+ };
57
+ }
58
+ getStatuses() {
59
+ const allStates = new Set();
60
+ for (const type of this.types) {
61
+ for (const state of type.states) {
62
+ allStates.add(state.name);
63
+ }
64
+ }
65
+ return [...allStates];
66
+ }
67
+ getWorkItemTypes() {
68
+ return this.types.map((t) => t.name);
69
+ }
70
+ getIterations() {
71
+ const iterations = az([
72
+ 'boards',
73
+ 'iteration',
74
+ 'team',
75
+ 'list',
76
+ '--team',
77
+ `${this.project} Team`,
78
+ '--org',
79
+ `https://dev.azure.com/${this.org}`,
80
+ '--project',
81
+ this.project,
82
+ ], this.cwd);
83
+ return iterations.map((i) => i.path);
84
+ }
85
+ getCurrentIteration() {
86
+ const iterations = az([
87
+ 'boards',
88
+ 'iteration',
89
+ 'team',
90
+ 'list',
91
+ '--team',
92
+ `${this.project} Team`,
93
+ '--timeframe',
94
+ 'current',
95
+ '--org',
96
+ `https://dev.azure.com/${this.org}`,
97
+ '--project',
98
+ this.project,
99
+ ], this.cwd);
100
+ return iterations[0]?.path ?? '';
101
+ }
102
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
103
+ setCurrentIteration(_name) {
104
+ // No-op — current iteration is determined by date range in ADO
105
+ }
106
+ escapeWiql(value) {
107
+ return value.replace(/'/g, "''");
108
+ }
109
+ batchFetchWorkItems(ids) {
110
+ const CHUNK_SIZE = 200;
111
+ const items = [];
112
+ for (let i = 0; i < ids.length; i += CHUNK_SIZE) {
113
+ const chunk = ids.slice(i, i + CHUNK_SIZE);
114
+ const batchResult = azInvoke({
115
+ area: 'wit',
116
+ resource: 'workitemsbatch',
117
+ httpMethod: 'POST',
118
+ body: { ids: chunk, fields: BATCH_FIELDS, $expand: 4 },
119
+ apiVersion: '7.1',
120
+ }, this.cwd);
121
+ items.push(...batchResult.value.map(mapWorkItemToWorkItem));
122
+ }
123
+ return items;
124
+ }
125
+ listWorkItems(iteration) {
126
+ let wiql = `SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = '${this.escapeWiql(this.project)}'`;
127
+ if (iteration) {
128
+ wiql += ` AND [System.IterationPath] = '${this.escapeWiql(iteration)}'`;
129
+ }
130
+ const queryResult = az([
131
+ 'boards',
132
+ 'query',
133
+ '--wiql',
134
+ wiql,
135
+ '--org',
136
+ `https://dev.azure.com/${this.org}`,
137
+ '--project',
138
+ this.project,
139
+ ], this.cwd);
140
+ const ids = queryResult.workItems.map((w) => w.id);
141
+ if (ids.length === 0)
142
+ return [];
143
+ const items = this.batchFetchWorkItems(ids);
144
+ items.sort((a, b) => b.updated.localeCompare(a.updated));
145
+ return items;
146
+ }
147
+ getWorkItem(id) {
148
+ const ado = az([
149
+ 'boards',
150
+ 'work-item',
151
+ 'show',
152
+ '--id',
153
+ id,
154
+ '--expand',
155
+ 'relations',
156
+ '--org',
157
+ `https://dev.azure.com/${this.org}`,
158
+ '--project',
159
+ this.project,
160
+ ], this.cwd);
161
+ const item = mapWorkItemToWorkItem(ado);
162
+ // Fetch comments
163
+ const commentResult = azInvoke({
164
+ area: 'wit',
165
+ resource: 'comments',
166
+ routeParameters: `workItemId=${id}`,
167
+ apiVersion: '7.1',
168
+ }, this.cwd);
169
+ item.comments = (commentResult.comments ?? []).map(mapCommentToComment);
170
+ return item;
171
+ }
172
+ createWorkItem(data) {
173
+ this.validateFields(data);
174
+ const args = [
175
+ 'boards',
176
+ 'work-item',
177
+ 'create',
178
+ '--type',
179
+ data.type,
180
+ '--title',
181
+ data.title,
182
+ '--org',
183
+ `https://dev.azure.com/${this.org}`,
184
+ '--project',
185
+ this.project,
186
+ ];
187
+ const fields = [];
188
+ if (data.status)
189
+ fields.push(`System.State=${data.status}`);
190
+ if (data.iteration)
191
+ fields.push(`System.IterationPath=${data.iteration}`);
192
+ if (data.priority)
193
+ fields.push(`Microsoft.VSTS.Common.Priority=${mapPriorityToAdo(data.priority)}`);
194
+ if (data.assignee)
195
+ fields.push(`System.AssignedTo=${data.assignee}`);
196
+ if (data.labels.length > 0)
197
+ fields.push(`System.Tags=${formatTags(data.labels)}`);
198
+ if (data.description)
199
+ fields.push(`System.Description=${data.description}`);
200
+ for (const field of fields) {
201
+ args.push('--fields', field);
202
+ }
203
+ const created = az(args, this.cwd);
204
+ const createdId = String(created.id);
205
+ // Add parent relation if specified
206
+ if (data.parent) {
207
+ azExec([
208
+ 'boards',
209
+ 'work-item',
210
+ 'relation',
211
+ 'add',
212
+ '--id',
213
+ createdId,
214
+ '--relation-type',
215
+ 'System.LinkTypes.Hierarchy-Reverse',
216
+ '--target-id',
217
+ data.parent,
218
+ '--org',
219
+ `https://dev.azure.com/${this.org}`,
220
+ ], this.cwd);
221
+ }
222
+ // Add dependency relations
223
+ for (const depId of data.dependsOn) {
224
+ azExec([
225
+ 'boards',
226
+ 'work-item',
227
+ 'relation',
228
+ 'add',
229
+ '--id',
230
+ createdId,
231
+ '--relation-type',
232
+ 'System.LinkTypes.Dependency-Reverse',
233
+ '--target-id',
234
+ depId,
235
+ '--org',
236
+ `https://dev.azure.com/${this.org}`,
237
+ ], this.cwd);
238
+ }
239
+ return this.getWorkItem(createdId);
240
+ }
241
+ updateWorkItem(id, data) {
242
+ this.validateFields(data);
243
+ const args = [
244
+ 'boards',
245
+ 'work-item',
246
+ 'update',
247
+ '--id',
248
+ id,
249
+ '--org',
250
+ `https://dev.azure.com/${this.org}`,
251
+ '--project',
252
+ this.project,
253
+ ];
254
+ const fields = [];
255
+ if (data.title !== undefined)
256
+ fields.push(`System.Title=${data.title}`);
257
+ if (data.status !== undefined)
258
+ fields.push(`System.State=${data.status}`);
259
+ if (data.iteration !== undefined)
260
+ fields.push(`System.IterationPath=${data.iteration}`);
261
+ if (data.priority !== undefined)
262
+ fields.push(`Microsoft.VSTS.Common.Priority=${mapPriorityToAdo(data.priority)}`);
263
+ if (data.assignee !== undefined)
264
+ fields.push(`System.AssignedTo=${data.assignee}`);
265
+ if (data.labels !== undefined)
266
+ fields.push(`System.Tags=${formatTags(data.labels)}`);
267
+ if (data.description !== undefined)
268
+ fields.push(`System.Description=${data.description}`);
269
+ for (const field of fields) {
270
+ args.push('--fields', field);
271
+ }
272
+ if (fields.length > 0) {
273
+ az(args, this.cwd);
274
+ }
275
+ // Handle parent relation changes
276
+ if (data.parent !== undefined) {
277
+ const current = az([
278
+ 'boards',
279
+ 'work-item',
280
+ 'show',
281
+ '--id',
282
+ id,
283
+ '--expand',
284
+ 'relations',
285
+ '--org',
286
+ `https://dev.azure.com/${this.org}`,
287
+ '--project',
288
+ this.project,
289
+ ], this.cwd);
290
+ const currentParent = extractParent(current.relations);
291
+ if (currentParent && currentParent !== data.parent) {
292
+ azExec([
293
+ 'boards',
294
+ 'work-item',
295
+ 'relation',
296
+ 'remove',
297
+ '--id',
298
+ id,
299
+ '--relation-type',
300
+ 'System.LinkTypes.Hierarchy-Reverse',
301
+ '--target-id',
302
+ currentParent,
303
+ '--org',
304
+ `https://dev.azure.com/${this.org}`,
305
+ '--yes',
306
+ ], this.cwd);
307
+ }
308
+ if (data.parent && data.parent !== currentParent) {
309
+ azExec([
310
+ 'boards',
311
+ 'work-item',
312
+ 'relation',
313
+ 'add',
314
+ '--id',
315
+ id,
316
+ '--relation-type',
317
+ 'System.LinkTypes.Hierarchy-Reverse',
318
+ '--target-id',
319
+ data.parent,
320
+ '--org',
321
+ `https://dev.azure.com/${this.org}`,
322
+ ], this.cwd);
323
+ }
324
+ }
325
+ // Handle dependency relation changes
326
+ if (data.dependsOn !== undefined) {
327
+ const current = az([
328
+ 'boards',
329
+ 'work-item',
330
+ 'show',
331
+ '--id',
332
+ id,
333
+ '--expand',
334
+ 'relations',
335
+ '--org',
336
+ `https://dev.azure.com/${this.org}`,
337
+ '--project',
338
+ this.project,
339
+ ], this.cwd);
340
+ const currentDeps = new Set(extractPredecessors(current.relations));
341
+ const newDeps = new Set(data.dependsOn);
342
+ // Remove deps that are no longer in the list
343
+ for (const dep of currentDeps) {
344
+ if (!newDeps.has(dep)) {
345
+ azExec([
346
+ 'boards',
347
+ 'work-item',
348
+ 'relation',
349
+ 'remove',
350
+ '--id',
351
+ id,
352
+ '--relation-type',
353
+ 'System.LinkTypes.Dependency-Reverse',
354
+ '--target-id',
355
+ dep,
356
+ '--org',
357
+ `https://dev.azure.com/${this.org}`,
358
+ '--yes',
359
+ ], this.cwd);
360
+ }
361
+ }
362
+ // Add deps that are new
363
+ for (const dep of newDeps) {
364
+ if (!currentDeps.has(dep)) {
365
+ azExec([
366
+ 'boards',
367
+ 'work-item',
368
+ 'relation',
369
+ 'add',
370
+ '--id',
371
+ id,
372
+ '--relation-type',
373
+ 'System.LinkTypes.Dependency-Reverse',
374
+ '--target-id',
375
+ dep,
376
+ '--org',
377
+ `https://dev.azure.com/${this.org}`,
378
+ ], this.cwd);
379
+ }
380
+ }
381
+ }
382
+ return this.getWorkItem(id);
383
+ }
384
+ deleteWorkItem(id) {
385
+ azExec([
386
+ 'boards',
387
+ 'work-item',
388
+ 'delete',
389
+ '--id',
390
+ id,
391
+ '--yes',
392
+ '--org',
393
+ `https://dev.azure.com/${this.org}`,
394
+ '--project',
395
+ this.project,
396
+ ], this.cwd);
397
+ }
398
+ addComment(workItemId, comment) {
399
+ azInvoke({
400
+ area: 'wit',
401
+ resource: 'comments',
402
+ routeParameters: `workItemId=${workItemId}`,
403
+ httpMethod: 'POST',
404
+ body: { text: comment.body },
405
+ apiVersion: '7.1',
406
+ }, this.cwd);
407
+ return {
408
+ author: comment.author,
409
+ date: new Date().toISOString(),
410
+ body: comment.body,
411
+ };
412
+ }
413
+ getChildren(id) {
414
+ const numericId = parseInt(id, 10);
415
+ if (isNaN(numericId))
416
+ throw new Error(`Invalid work item ID: "${id}"`);
417
+ const wiql = `SELECT [System.Id] FROM WorkItemLinks WHERE [Source].[System.Id] = ${numericId} AND [System.Links.LinkType] = 'System.LinkTypes.Hierarchy-Forward' MODE (MustContain)`;
418
+ const queryResult = az([
419
+ 'boards',
420
+ 'query',
421
+ '--wiql',
422
+ wiql,
423
+ '--org',
424
+ `https://dev.azure.com/${this.org}`,
425
+ '--project',
426
+ this.project,
427
+ ], this.cwd);
428
+ const ids = queryResult.workItems?.map((w) => w.id) ?? [];
429
+ if (ids.length === 0)
430
+ return [];
431
+ return this.batchFetchWorkItems(ids);
432
+ }
433
+ getDependents(id) {
434
+ const numericId = parseInt(id, 10);
435
+ if (isNaN(numericId))
436
+ throw new Error(`Invalid work item ID: "${id}"`);
437
+ const wiql = `SELECT [System.Id] FROM WorkItemLinks WHERE [Source].[System.Id] = ${numericId} AND [System.Links.LinkType] = 'System.LinkTypes.Dependency-Forward' MODE (MustContain)`;
438
+ const queryResult = az([
439
+ 'boards',
440
+ 'query',
441
+ '--wiql',
442
+ wiql,
443
+ '--org',
444
+ `https://dev.azure.com/${this.org}`,
445
+ '--project',
446
+ this.project,
447
+ ], this.cwd);
448
+ const ids = queryResult.workItems?.map((w) => w.id) ?? [];
449
+ if (ids.length === 0)
450
+ return [];
451
+ return this.batchFetchWorkItems(ids);
452
+ }
453
+ getItemUrl(id) {
454
+ return `https://dev.azure.com/${this.org}/${encodeURIComponent(this.project)}/_workitems/edit/${id}`;
455
+ }
456
+ openItem(id) {
457
+ const url = this.getItemUrl(id);
458
+ execFileSync('open', [url]);
459
+ }
460
+ }
461
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/backends/ado/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import type { WorkItem, Comment } from '../../types.js';
2
+ export interface AdoWorkItem {
3
+ id: number;
4
+ fields: Record<string, unknown>;
5
+ relations?: AdoRelation[];
6
+ }
7
+ export interface AdoRelation {
8
+ rel: string;
9
+ url: string;
10
+ attributes: Record<string, unknown>;
11
+ }
12
+ export interface AdoComment {
13
+ createdBy: {
14
+ displayName: string;
15
+ };
16
+ createdDate: string;
17
+ text: string;
18
+ }
19
+ export interface AdoIteration {
20
+ name: string;
21
+ path: string;
22
+ attributes: {
23
+ startDate?: string;
24
+ finishDate?: string;
25
+ };
26
+ }
27
+ export interface AdoWorkItemType {
28
+ name: string;
29
+ states: {
30
+ name: string;
31
+ }[];
32
+ }
33
+ export declare function mapPriorityToTic(priority: number | undefined): 'critical' | 'high' | 'medium' | 'low';
34
+ export declare function mapPriorityToAdo(priority: string): number;
35
+ export declare function parseTags(tags: string | undefined): string[];
36
+ export declare function formatTags(tags: string[]): string;
37
+ export declare function extractParent(relations: AdoRelation[] | undefined): string | null;
38
+ export declare function extractPredecessors(relations: AdoRelation[] | undefined): string[];
39
+ export declare function mapWorkItemToWorkItem(ado: AdoWorkItem): WorkItem;
40
+ export declare function mapCommentToComment(ado: AdoComment): Comment;
@@ -0,0 +1,92 @@
1
+ import TurndownService from 'turndown';
2
+ const turndown = new TurndownService();
3
+ export function mapPriorityToTic(priority) {
4
+ switch (priority) {
5
+ case 1:
6
+ return 'critical';
7
+ case 2:
8
+ return 'high';
9
+ case 3:
10
+ return 'medium';
11
+ case 4:
12
+ return 'low';
13
+ default:
14
+ return 'medium';
15
+ }
16
+ }
17
+ export function mapPriorityToAdo(priority) {
18
+ switch (priority) {
19
+ case 'critical':
20
+ return 1;
21
+ case 'high':
22
+ return 2;
23
+ case 'medium':
24
+ return 3;
25
+ case 'low':
26
+ return 4;
27
+ default:
28
+ return 3;
29
+ }
30
+ }
31
+ export function parseTags(tags) {
32
+ if (!tags)
33
+ return [];
34
+ return tags
35
+ .split(';')
36
+ .map((t) => t.trim())
37
+ .filter((t) => t.length > 0);
38
+ }
39
+ export function formatTags(tags) {
40
+ return tags.join('; ');
41
+ }
42
+ function extractIdFromUrl(url) {
43
+ const match = url.match(/\/workItems\/(\d+)$/);
44
+ return match ? match[1] : '';
45
+ }
46
+ export function extractParent(relations) {
47
+ if (!relations)
48
+ return null;
49
+ const parent = relations.find((r) => r.rel === 'System.LinkTypes.Hierarchy-Reverse');
50
+ return parent ? extractIdFromUrl(parent.url) || null : null;
51
+ }
52
+ export function extractPredecessors(relations) {
53
+ if (!relations)
54
+ return [];
55
+ return relations
56
+ .filter((r) => r.rel === 'System.LinkTypes.Dependency-Reverse')
57
+ .map((r) => extractIdFromUrl(r.url))
58
+ .filter((id) => id !== '');
59
+ }
60
+ function htmlToMarkdown(html) {
61
+ if (!html)
62
+ return '';
63
+ return turndown.turndown(html);
64
+ }
65
+ export function mapWorkItemToWorkItem(ado) {
66
+ const fields = ado.fields;
67
+ const assignedTo = fields['System.AssignedTo'];
68
+ return {
69
+ id: String(ado.id),
70
+ title: fields['System.Title'] ?? '',
71
+ type: fields['System.WorkItemType'] ?? '',
72
+ status: fields['System.State'] ?? '',
73
+ iteration: fields['System.IterationPath'] ?? '',
74
+ priority: mapPriorityToTic(fields['Microsoft.VSTS.Common.Priority']),
75
+ assignee: assignedTo?.displayName ?? '',
76
+ labels: parseTags(fields['System.Tags']),
77
+ description: htmlToMarkdown(fields['System.Description']),
78
+ created: fields['System.CreatedDate'] ?? '',
79
+ updated: fields['System.ChangedDate'] ?? '',
80
+ parent: extractParent(ado.relations),
81
+ dependsOn: extractPredecessors(ado.relations),
82
+ comments: [],
83
+ };
84
+ }
85
+ export function mapCommentToComment(ado) {
86
+ return {
87
+ author: ado.createdBy.displayName,
88
+ date: ado.createdDate,
89
+ body: htmlToMarkdown(ado.text),
90
+ };
91
+ }
92
+ //# sourceMappingURL=mappers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mappers.js","sourceRoot":"","sources":["../../../src/backends/ado/mappers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export interface AdoRemoteInfo {
2
+ org: string;
3
+ project: string;
4
+ }
5
+ export declare function parseAdoRemote(cwd: string): AdoRemoteInfo;
@@ -0,0 +1,37 @@
1
+ import { execSync } from 'node:child_process';
2
+ export function parseAdoRemote(cwd) {
3
+ const output = execSync('git remote -v', {
4
+ cwd,
5
+ encoding: 'utf-8',
6
+ stdio: ['pipe', 'pipe', 'pipe'],
7
+ });
8
+ const lines = output.split('\n');
9
+ for (const line of lines) {
10
+ // HTTPS: https://dev.azure.com/{org}/{project}/_git/{repo}
11
+ const httpsMatch = line.match(/dev\.azure\.com\/([^/]+)\/([^/]+)\/_git\//);
12
+ if (httpsMatch) {
13
+ return {
14
+ org: httpsMatch[1],
15
+ project: decodeURIComponent(httpsMatch[2]),
16
+ };
17
+ }
18
+ // SSH: git@ssh.dev.azure.com:v3/{org}/{project}/{repo}
19
+ const sshMatch = line.match(/ssh\.dev\.azure\.com:v3\/([^/]+)\/([^/]+)\/[^/]+/);
20
+ if (sshMatch) {
21
+ return {
22
+ org: sshMatch[1],
23
+ project: decodeURIComponent(sshMatch[2]),
24
+ };
25
+ }
26
+ // Legacy: https://{org}.visualstudio.com/{project}/_git/{repo}
27
+ const legacyMatch = line.match(/([^/.]+)\.visualstudio\.com\/([^/]+)\/_git\//);
28
+ if (legacyMatch) {
29
+ return {
30
+ org: legacyMatch[1],
31
+ project: decodeURIComponent(legacyMatch[2]),
32
+ };
33
+ }
34
+ }
35
+ throw new Error('No Azure DevOps remote found in git remotes');
36
+ }
37
+ //# sourceMappingURL=remote.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote.js","sourceRoot":"","sources":["../../../src/backends/ado/remote.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAO9C,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,MAAM,MAAM,GAAG,QAAQ,CAAC,eAAe,EAAE;QACvC,GAAG;QACH,QAAQ,EAAE,OAAO;QACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;KAChC,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACjC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,2DAA2D;QAC3D,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC3E,IAAI,UAAU,EAAE,CAAC;YACf,OAAO;gBACL,GAAG,EAAE,UAAU,CAAC,CAAC,CAAE;gBACnB,OAAO,EAAE,kBAAkB,CAAC,UAAU,CAAC,CAAC,CAAE,CAAC;aAC5C,CAAC;QACJ,CAAC;QAED,uDAAuD;QACvD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CACzB,kDAAkD,CACnD,CAAC;QACF,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO;gBACL,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAE;gBACjB,OAAO,EAAE,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAAE,CAAC;aAC1C,CAAC;QACJ,CAAC;QAED,+DAA+D;QAC/D,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAC5B,8CAA8C,CAC/C,CAAC;QACF,IAAI,WAAW,EAAE,CAAC;YAChB,OAAO;gBACL,GAAG,EAAE,WAAW,CAAC,CAAC,CAAE;gBACpB,OAAO,EAAE,kBAAkB,CAAC,WAAW,CAAC,CAAC,CAAE,CAAC;aAC7C,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;AACjE,CAAC"}
@@ -2,6 +2,7 @@ import { execSync } from 'node:child_process';
2
2
  import { LocalBackend } from './local/index.js';
3
3
  import { GitHubBackend } from './github/index.js';
4
4
  import { GitLabBackend } from './gitlab/index.js';
5
+ import { AzureDevOpsBackend } from './ado/index.js';
5
6
  import { readConfig } from './local/config.js';
6
7
  export const VALID_BACKENDS = ['local', 'github', 'gitlab', 'azure'];
7
8
  export function detectBackend(root) {
@@ -15,7 +16,9 @@ export function detectBackend(root) {
15
16
  return 'github';
16
17
  if (output.includes('gitlab.com'))
17
18
  return 'gitlab';
18
- if (output.includes('dev.azure.com'))
19
+ if (output.includes('dev.azure.com') ||
20
+ output.includes('ssh.dev.azure.com') ||
21
+ /\w+\.visualstudio\.com/.test(output))
19
22
  return 'azure';
20
23
  }
21
24
  catch {
@@ -34,7 +37,7 @@ export function createBackend(root) {
34
37
  case 'gitlab':
35
38
  return new GitLabBackend(root);
36
39
  case 'azure':
37
- throw new Error(`Backend "${backend}" is not yet implemented. Use "local" for now.`);
40
+ return new AzureDevOpsBackend(root);
38
41
  default:
39
42
  throw new Error(`Unknown backend "${backend}". Valid backends: ${VALID_BACKENDS.join(', ')}`);
40
43
  }
@@ -1 +1 @@
1
- {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/backends/factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAU,CAAC;AAG9E,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,QAAQ,CAAC,eAAe,EAAE;YACvC,GAAG,EAAE,IAAI;YACT,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC;QACH,IAAI,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC;YAAE,OAAO,QAAQ,CAAC;QACnD,IAAI,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC;YAAE,OAAO,QAAQ,CAAC;QACnD,IAAI,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC;YAAE,OAAO,OAAO,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,sCAAsC;IACxC,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,OAAO,CAAC;IAE1C,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,OAAO;YACV,OAAO,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;QAChC,KAAK,QAAQ;YACX,OAAO,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC;QACjC,KAAK,QAAQ;YACX,OAAO,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC;QACjC,KAAK,OAAO;YACV,MAAM,IAAI,KAAK,CACb,YAAY,OAAO,gDAAgD,CACpE,CAAC;QACJ;YACE,MAAM,IAAI,KAAK,CACb,oBAAoB,OAAO,sBAAsB,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC7E,CAAC;IACN,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/backends/factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAU,CAAC;AAG9E,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,QAAQ,CAAC,eAAe,EAAE;YACvC,GAAG,EAAE,IAAI;YACT,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC;QACH,IAAI,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC;YAAE,OAAO,QAAQ,CAAC;QACnD,IAAI,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC;YAAE,OAAO,QAAQ,CAAC;QACnD,IACE,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC;YAChC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAC;YACpC,wBAAwB,CAAC,IAAI,CAAC,MAAM,CAAC;YAErC,OAAO,OAAO,CAAC;IACnB,CAAC;IAAC,MAAM,CAAC;QACP,sCAAsC;IACxC,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,OAAO,CAAC;IAE1C,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,OAAO;YACV,OAAO,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;QAChC,KAAK,QAAQ;YACX,OAAO,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC;QACjC,KAAK,QAAQ;YACX,OAAO,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC;QACjC,KAAK,OAAO;YACV,OAAO,IAAI,kBAAkB,CAAC,IAAI,CAAC,CAAC;QACtC;YACE,MAAM,IAAI,KAAK,CACb,oBAAoB,OAAO,sBAAsB,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC7E,CAAC;IACN,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sascha384/tic",
3
- "version": "0.1.0",
3
+ "version": "1.0.0",
4
4
  "description": "Terminal UI for issue tracking",
5
5
  "type": "module",
6
6
  "bin": {
@@ -37,6 +37,7 @@
37
37
  "ink-select-input": "^6.2.0",
38
38
  "ink-text-input": "^6.0.0",
39
39
  "react": "^19.2.4",
40
+ "turndown": "^7.2.2",
40
41
  "yaml": "^2.8.2",
41
42
  "zod": "^4.3.6"
42
43
  },
@@ -45,6 +46,7 @@
45
46
  "@sindresorhus/tsconfig": "^8.1.0",
46
47
  "@types/node": "^25.1.0",
47
48
  "@types/react": "^19.2.10",
49
+ "@types/turndown": "^5.0.6",
48
50
  "eslint": "^9.39.2",
49
51
  "eslint-config-prettier": "^10.1.8",
50
52
  "husky": "^9.1.7",
@@ -55,7 +57,9 @@
55
57
  "vitest": "^4.0.18"
56
58
  },
57
59
  "release": {
58
- "branches": ["main"],
60
+ "branches": [
61
+ "main"
62
+ ],
59
63
  "plugins": [
60
64
  "@semantic-release/commit-analyzer",
61
65
  "@semantic-release/release-notes-generator",