github-issue-tower-defence-management 1.85.0 → 1.87.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.
Files changed (64) hide show
  1. package/.eslintrc.cjs +5 -1
  2. package/.github/workflows/console-ui.yml +47 -0
  3. package/.prettierignore +3 -0
  4. package/CHANGELOG.md +15 -0
  5. package/README.md +12 -0
  6. package/bin/adapter/entry-points/cli/index.js +37 -0
  7. package/bin/adapter/entry-points/cli/index.js.map +1 -1
  8. package/bin/adapter/entry-points/cli/projectConfig.js +2 -0
  9. package/bin/adapter/entry-points/cli/projectConfig.js.map +1 -1
  10. package/bin/adapter/entry-points/console/consoleServer.js +204 -0
  11. package/bin/adapter/entry-points/console/consoleServer.js.map +1 -0
  12. package/bin/adapter/entry-points/console/ui-dist/assets/index-DFxrSRH4.css +1 -0
  13. package/bin/adapter/entry-points/console/ui-dist/assets/index-DcOZ02ON.js +49 -0
  14. package/bin/adapter/entry-points/console/ui-dist/index.html +13 -0
  15. package/bin/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.js +306 -0
  16. package/bin/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.js.map +1 -1
  17. package/package.json +22 -2
  18. package/scripts/copyConsoleUiDist.mjs +35 -0
  19. package/src/adapter/entry-points/cli/index.test.ts +126 -0
  20. package/src/adapter/entry-points/cli/index.ts +66 -0
  21. package/src/adapter/entry-points/cli/projectConfig.ts +4 -0
  22. package/src/adapter/entry-points/console/consoleServer.test.ts +297 -0
  23. package/src/adapter/entry-points/console/consoleServer.ts +220 -0
  24. package/src/adapter/entry-points/console/ui/.storybook/main.ts +12 -0
  25. package/src/adapter/entry-points/console/ui/.storybook/preview.ts +15 -0
  26. package/src/adapter/entry-points/console/ui/biome.json +47 -0
  27. package/src/adapter/entry-points/console/ui/components.json +20 -0
  28. package/src/adapter/entry-points/console/ui/index.html +12 -0
  29. package/src/adapter/entry-points/console/ui/src/components/ui/badge.stories.tsx +35 -0
  30. package/src/adapter/entry-points/console/ui/src/components/ui/badge.tsx +28 -0
  31. package/src/adapter/entry-points/console/ui/src/components/ui/button.stories.tsx +34 -0
  32. package/src/adapter/entry-points/console/ui/src/components/ui/button.tsx +50 -0
  33. package/src/adapter/entry-points/console/ui/src/features/console/components/ConsoleListView.stories.tsx +44 -0
  34. package/src/adapter/entry-points/console/ui/src/features/console/components/ConsoleListView.tsx +58 -0
  35. package/src/adapter/entry-points/console/ui/src/features/console/components/ConsoleTabBar.stories.tsx +34 -0
  36. package/src/adapter/entry-points/console/ui/src/features/console/components/ConsoleTabBar.tsx +32 -0
  37. package/src/adapter/entry-points/console/ui/src/features/console/fixtures.ts +47 -0
  38. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleList.ts +65 -0
  39. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleToken.ts +64 -0
  40. package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsolePage.tsx +19 -0
  41. package/src/adapter/entry-points/console/ui/src/features/console/types.ts +69 -0
  42. package/src/adapter/entry-points/console/ui/src/index.css +31 -0
  43. package/src/adapter/entry-points/console/ui/src/lib/utils.ts +4 -0
  44. package/src/adapter/entry-points/console/ui/src/main.tsx +15 -0
  45. package/src/adapter/entry-points/console/ui/src/vite-env.d.ts +1 -0
  46. package/src/adapter/entry-points/console/ui/tsconfig.json +24 -0
  47. package/src/adapter/entry-points/console/ui/vite.config.ts +19 -0
  48. package/src/adapter/entry-points/console/ui-dist/assets/index-DFxrSRH4.css +1 -0
  49. package/src/adapter/entry-points/console/ui-dist/assets/index-DcOZ02ON.js +49 -0
  50. package/src/adapter/entry-points/console/ui-dist/index.html +13 -0
  51. package/src/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.test.ts +630 -0
  52. package/src/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.ts +492 -0
  53. package/src/domain/usecases/adapter-interfaces/IssueRepository.ts +51 -0
  54. package/tsconfig.build.json +7 -1
  55. package/tsconfig.json +6 -1
  56. package/types/adapter/entry-points/cli/index.d.ts.map +1 -1
  57. package/types/adapter/entry-points/cli/projectConfig.d.ts +1 -0
  58. package/types/adapter/entry-points/cli/projectConfig.d.ts.map +1 -1
  59. package/types/adapter/entry-points/console/consoleServer.d.ts +19 -0
  60. package/types/adapter/entry-points/console/consoleServer.d.ts.map +1 -0
  61. package/types/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.d.ts +18 -1
  62. package/types/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.d.ts.map +1 -1
  63. package/types/domain/usecases/adapter-interfaces/IssueRepository.d.ts +47 -0
  64. package/types/domain/usecases/adapter-interfaces/IssueRepository.d.ts.map +1 -1
@@ -1,6 +1,10 @@
1
1
  import {
2
2
  IssueRepository,
3
3
  RelatedPullRequest,
4
+ IssueComment,
5
+ PullRequestDetail,
6
+ PullRequestFile,
7
+ PullRequestCommit,
4
8
  } from '../../../domain/usecases/adapter-interfaces/IssueRepository';
5
9
  import { Project } from '../../../domain/entities/Project';
6
10
  import { Issue } from '../../../domain/entities/Issue';
@@ -226,6 +230,163 @@ function isPullRequestFilesResponse(
226
230
  );
227
231
  }
228
232
 
233
+ function isRecord(value: unknown): value is Record<string, unknown> {
234
+ return typeof value === 'object' && value !== null;
235
+ }
236
+
237
+ function isNullableString(value: unknown): value is string | null {
238
+ return value === null || typeof value === 'string';
239
+ }
240
+
241
+ function isLoginContainer(value: unknown): value is { login: string } {
242
+ return isRecord(value) && typeof value.login === 'string';
243
+ }
244
+
245
+ function isRefContainer(value: unknown): value is { ref: string } {
246
+ return isRecord(value) && typeof value.ref === 'string';
247
+ }
248
+
249
+ type IssueOrPullRequestBodyResponse = {
250
+ body: string | null;
251
+ };
252
+
253
+ function isIssueOrPullRequestBodyResponse(
254
+ value: unknown,
255
+ ): value is IssueOrPullRequestBodyResponse {
256
+ return isRecord(value) && isNullableString(value.body);
257
+ }
258
+
259
+ type IssueOrPullRequestStateResponse = {
260
+ state: string;
261
+ };
262
+
263
+ function isIssueOrPullRequestStateResponse(
264
+ value: unknown,
265
+ ): value is IssueOrPullRequestStateResponse {
266
+ return isRecord(value) && typeof value.state === 'string';
267
+ }
268
+
269
+ type IssueCommentsResponseItem = {
270
+ user: { login: string } | null;
271
+ body: string | null;
272
+ created_at: string;
273
+ };
274
+
275
+ function isIssueCommentsResponseItem(
276
+ value: unknown,
277
+ ): value is IssueCommentsResponseItem {
278
+ if (!isRecord(value)) return false;
279
+ const userValid = value.user === null || isLoginContainer(value.user);
280
+ return (
281
+ userValid &&
282
+ isNullableString(value.body) &&
283
+ typeof value.created_at === 'string'
284
+ );
285
+ }
286
+
287
+ function isIssueCommentsResponse(
288
+ value: unknown,
289
+ ): value is IssueCommentsResponseItem[] {
290
+ return Array.isArray(value) && value.every(isIssueCommentsResponseItem);
291
+ }
292
+
293
+ type PullRequestDetailResponse = {
294
+ title: string;
295
+ state: string;
296
+ merged: boolean;
297
+ draft: boolean;
298
+ additions: number;
299
+ deletions: number;
300
+ changed_files: number;
301
+ head: { ref: string };
302
+ base: { ref: string };
303
+ user: { login: string } | null;
304
+ body: string | null;
305
+ };
306
+
307
+ function isPullRequestDetailResponse(
308
+ value: unknown,
309
+ ): value is PullRequestDetailResponse {
310
+ if (!isRecord(value)) return false;
311
+ const userValid = value.user === null || isLoginContainer(value.user);
312
+ return (
313
+ typeof value.title === 'string' &&
314
+ typeof value.state === 'string' &&
315
+ typeof value.merged === 'boolean' &&
316
+ typeof value.draft === 'boolean' &&
317
+ typeof value.additions === 'number' &&
318
+ typeof value.deletions === 'number' &&
319
+ typeof value.changed_files === 'number' &&
320
+ isRefContainer(value.head) &&
321
+ isRefContainer(value.base) &&
322
+ userValid &&
323
+ isNullableString(value.body)
324
+ );
325
+ }
326
+
327
+ type PullRequestDetailFilesResponseItem = {
328
+ filename: string;
329
+ status: string;
330
+ additions: number;
331
+ deletions: number;
332
+ patch?: string;
333
+ };
334
+
335
+ function isPullRequestDetailFilesResponseItem(
336
+ value: unknown,
337
+ ): value is PullRequestDetailFilesResponseItem {
338
+ if (!isRecord(value)) return false;
339
+ return (
340
+ typeof value.filename === 'string' &&
341
+ typeof value.status === 'string' &&
342
+ typeof value.additions === 'number' &&
343
+ typeof value.deletions === 'number' &&
344
+ (value.patch === undefined || typeof value.patch === 'string')
345
+ );
346
+ }
347
+
348
+ function isPullRequestDetailFilesResponse(
349
+ value: unknown,
350
+ ): value is PullRequestDetailFilesResponseItem[] {
351
+ return (
352
+ Array.isArray(value) && value.every(isPullRequestDetailFilesResponseItem)
353
+ );
354
+ }
355
+
356
+ type PullRequestCommitsResponseItem = {
357
+ sha: string;
358
+ commit: {
359
+ message: string;
360
+ author: { name: string; date: string } | null;
361
+ };
362
+ };
363
+
364
+ function isCommitAuthor(
365
+ value: unknown,
366
+ ): value is { name: string; date: string } {
367
+ return (
368
+ isRecord(value) &&
369
+ typeof value.name === 'string' &&
370
+ typeof value.date === 'string'
371
+ );
372
+ }
373
+
374
+ function isPullRequestCommitsResponseItem(
375
+ value: unknown,
376
+ ): value is PullRequestCommitsResponseItem {
377
+ if (!isRecord(value)) return false;
378
+ if (typeof value.sha !== 'string') return false;
379
+ if (!isRecord(value.commit)) return false;
380
+ if (typeof value.commit.message !== 'string') return false;
381
+ return value.commit.author === null || isCommitAuthor(value.commit.author);
382
+ }
383
+
384
+ function isPullRequestCommitsResponse(
385
+ value: unknown,
386
+ ): value is PullRequestCommitsResponseItem[] {
387
+ return Array.isArray(value) && value.every(isPullRequestCommitsResponseItem);
388
+ }
389
+
229
390
  const fnmatch = (pattern: string, str: string): boolean => {
230
391
  let regexStr = '^';
231
392
  let i = 0;
@@ -1243,4 +1404,335 @@ export class ApiV3CheerioRestIssueRepository
1243
1404
  ): Promise<void> => {
1244
1405
  await this.restIssueRepository.createComment(issueOrPrUrl, commentBody);
1245
1406
  };
1407
+
1408
+ getIssueOrPullRequestBody = async (url: string): Promise<string> => {
1409
+ const { owner, repo, issueNumber } = this.parseIssueUrl(url);
1410
+ const response = await fetch(
1411
+ `https://api.github.com/repos/${owner}/${repo}/issues/${issueNumber}`,
1412
+ {
1413
+ method: 'GET',
1414
+ headers: {
1415
+ Authorization: `Bearer ${this.ghToken}`,
1416
+ Accept: 'application/vnd.github+json',
1417
+ },
1418
+ },
1419
+ );
1420
+ if (!response.ok) {
1421
+ throw new Error(
1422
+ `Failed to fetch body for ${url}: HTTP ${response.status}`,
1423
+ );
1424
+ }
1425
+ const body: unknown = await response.json();
1426
+ if (!isIssueOrPullRequestBodyResponse(body)) {
1427
+ throw new Error(
1428
+ `Unexpected response shape when fetching body for ${url}`,
1429
+ );
1430
+ }
1431
+ return body.body ?? '';
1432
+ };
1433
+
1434
+ getIssueOrPullRequestComments = async (
1435
+ url: string,
1436
+ ): Promise<IssueComment[]> => {
1437
+ const { owner, repo, issueNumber } = this.parseIssueUrl(url);
1438
+ const perPage = 100;
1439
+ const collectedComments: IssueComment[] = [];
1440
+ let page = 1;
1441
+ let hasMore = true;
1442
+ while (hasMore) {
1443
+ const response = await fetch(
1444
+ `https://api.github.com/repos/${owner}/${repo}/issues/${issueNumber}/comments?per_page=${perPage}&page=${page}`,
1445
+ {
1446
+ method: 'GET',
1447
+ headers: {
1448
+ Authorization: `Bearer ${this.ghToken}`,
1449
+ Accept: 'application/vnd.github+json',
1450
+ },
1451
+ },
1452
+ );
1453
+ if (!response.ok) {
1454
+ throw new Error(
1455
+ `Failed to fetch comments for ${url}: HTTP ${response.status}`,
1456
+ );
1457
+ }
1458
+ const body: unknown = await response.json();
1459
+ if (!isIssueCommentsResponse(body)) {
1460
+ throw new Error(
1461
+ `Unexpected response shape when fetching comments for ${url}`,
1462
+ );
1463
+ }
1464
+ for (const comment of body) {
1465
+ collectedComments.push({
1466
+ author: comment.user?.login ?? '',
1467
+ body: comment.body ?? '',
1468
+ createdAt: new Date(comment.created_at),
1469
+ });
1470
+ }
1471
+ if (body.length < perPage) {
1472
+ hasMore = false;
1473
+ } else {
1474
+ page += 1;
1475
+ }
1476
+ }
1477
+ return collectedComments;
1478
+ };
1479
+
1480
+ getPullRequestDetail = async (
1481
+ prUrl: string,
1482
+ ): Promise<PullRequestDetail | null> => {
1483
+ const {
1484
+ owner,
1485
+ repo,
1486
+ issueNumber: prNumber,
1487
+ isPr,
1488
+ } = this.parseIssueUrl(prUrl);
1489
+ if (!isPr) {
1490
+ return null;
1491
+ }
1492
+ const detailResponse = await fetch(
1493
+ `https://api.github.com/repos/${owner}/${repo}/pulls/${prNumber}`,
1494
+ {
1495
+ method: 'GET',
1496
+ headers: {
1497
+ Authorization: `Bearer ${this.ghToken}`,
1498
+ Accept: 'application/vnd.github+json',
1499
+ },
1500
+ },
1501
+ );
1502
+ if (!detailResponse.ok) {
1503
+ throw new Error(
1504
+ `Failed to fetch detail for PR ${prUrl}: HTTP ${detailResponse.status}`,
1505
+ );
1506
+ }
1507
+ const detailBody: unknown = await detailResponse.json();
1508
+ if (!isPullRequestDetailResponse(detailBody)) {
1509
+ throw new Error(
1510
+ `Unexpected response shape when fetching detail for PR ${prUrl}`,
1511
+ );
1512
+ }
1513
+ const files = await this.fetchPullRequestFiles(
1514
+ owner,
1515
+ repo,
1516
+ prNumber,
1517
+ prUrl,
1518
+ );
1519
+ return {
1520
+ title: detailBody.title,
1521
+ state: detailBody.state,
1522
+ merged: detailBody.merged,
1523
+ isDraft: detailBody.draft,
1524
+ additions: detailBody.additions,
1525
+ deletions: detailBody.deletions,
1526
+ changedFiles: detailBody.changed_files,
1527
+ headRefName: detailBody.head.ref,
1528
+ baseRefName: detailBody.base.ref,
1529
+ author: detailBody.user?.login ?? '',
1530
+ files,
1531
+ };
1532
+ };
1533
+
1534
+ private fetchPullRequestFiles = async (
1535
+ owner: string,
1536
+ repo: string,
1537
+ prNumber: number,
1538
+ prUrl: string,
1539
+ ): Promise<PullRequestFile[]> => {
1540
+ const perPage = 100;
1541
+ const collectedFiles: PullRequestFile[] = [];
1542
+ let page = 1;
1543
+ let hasMore = true;
1544
+ while (hasMore) {
1545
+ const response = await fetch(
1546
+ `https://api.github.com/repos/${owner}/${repo}/pulls/${prNumber}/files?per_page=${perPage}&page=${page}`,
1547
+ {
1548
+ method: 'GET',
1549
+ headers: {
1550
+ Authorization: `Bearer ${this.ghToken}`,
1551
+ Accept: 'application/vnd.github+json',
1552
+ },
1553
+ },
1554
+ );
1555
+ if (!response.ok) {
1556
+ throw new Error(
1557
+ `Failed to fetch files for PR ${prUrl}: HTTP ${response.status}`,
1558
+ );
1559
+ }
1560
+ const body: unknown = await response.json();
1561
+ if (!isPullRequestDetailFilesResponse(body)) {
1562
+ throw new Error(
1563
+ `Unexpected response shape when fetching files for PR ${prUrl}`,
1564
+ );
1565
+ }
1566
+ for (const file of body) {
1567
+ collectedFiles.push({
1568
+ filename: file.filename,
1569
+ status: file.status,
1570
+ additions: file.additions,
1571
+ deletions: file.deletions,
1572
+ patch: file.patch ?? null,
1573
+ });
1574
+ }
1575
+ if (body.length < perPage) {
1576
+ hasMore = false;
1577
+ } else {
1578
+ page += 1;
1579
+ }
1580
+ }
1581
+ return collectedFiles;
1582
+ };
1583
+
1584
+ getPullRequestCommits = async (
1585
+ prUrl: string,
1586
+ ): Promise<PullRequestCommit[]> => {
1587
+ const {
1588
+ owner,
1589
+ repo,
1590
+ issueNumber: prNumber,
1591
+ isPr,
1592
+ } = this.parseIssueUrl(prUrl);
1593
+ if (!isPr) {
1594
+ return [];
1595
+ }
1596
+ const perPage = 100;
1597
+ const collectedCommits: PullRequestCommit[] = [];
1598
+ let page = 1;
1599
+ let hasMore = true;
1600
+ while (hasMore) {
1601
+ const response = await fetch(
1602
+ `https://api.github.com/repos/${owner}/${repo}/pulls/${prNumber}/commits?per_page=${perPage}&page=${page}`,
1603
+ {
1604
+ method: 'GET',
1605
+ headers: {
1606
+ Authorization: `Bearer ${this.ghToken}`,
1607
+ Accept: 'application/vnd.github+json',
1608
+ },
1609
+ },
1610
+ );
1611
+ if (!response.ok) {
1612
+ throw new Error(
1613
+ `Failed to fetch commits for PR ${prUrl}: HTTP ${response.status}`,
1614
+ );
1615
+ }
1616
+ const body: unknown = await response.json();
1617
+ if (!isPullRequestCommitsResponse(body)) {
1618
+ throw new Error(
1619
+ `Unexpected response shape when fetching commits for PR ${prUrl}`,
1620
+ );
1621
+ }
1622
+ for (const commit of body) {
1623
+ collectedCommits.push({
1624
+ sha: commit.sha,
1625
+ message: commit.commit.message,
1626
+ author: commit.commit.author?.name ?? '',
1627
+ authoredAt: new Date(commit.commit.author?.date ?? 0),
1628
+ });
1629
+ }
1630
+ if (body.length < perPage) {
1631
+ hasMore = false;
1632
+ } else {
1633
+ page += 1;
1634
+ }
1635
+ }
1636
+ return collectedCommits;
1637
+ };
1638
+
1639
+ getIssueOrPullRequestState = async (
1640
+ url: string,
1641
+ ): Promise<{ state: string; merged: boolean; isPullRequest: boolean }> => {
1642
+ const { owner, repo, issueNumber, isPr } = this.parseIssueUrl(url);
1643
+ if (isPr) {
1644
+ const response = await fetch(
1645
+ `https://api.github.com/repos/${owner}/${repo}/pulls/${issueNumber}`,
1646
+ {
1647
+ method: 'GET',
1648
+ headers: {
1649
+ Authorization: `Bearer ${this.ghToken}`,
1650
+ Accept: 'application/vnd.github+json',
1651
+ },
1652
+ },
1653
+ );
1654
+ if (!response.ok) {
1655
+ throw new Error(
1656
+ `Failed to fetch state for ${url}: HTTP ${response.status}`,
1657
+ );
1658
+ }
1659
+ const body: unknown = await response.json();
1660
+ if (!isPullRequestDetailResponse(body)) {
1661
+ throw new Error(
1662
+ `Unexpected response shape when fetching state for ${url}`,
1663
+ );
1664
+ }
1665
+ return { state: body.state, merged: body.merged, isPullRequest: true };
1666
+ }
1667
+ const response = await fetch(
1668
+ `https://api.github.com/repos/${owner}/${repo}/issues/${issueNumber}`,
1669
+ {
1670
+ method: 'GET',
1671
+ headers: {
1672
+ Authorization: `Bearer ${this.ghToken}`,
1673
+ Accept: 'application/vnd.github+json',
1674
+ },
1675
+ },
1676
+ );
1677
+ if (!response.ok) {
1678
+ throw new Error(
1679
+ `Failed to fetch state for ${url}: HTTP ${response.status}`,
1680
+ );
1681
+ }
1682
+ const body: unknown = await response.json();
1683
+ if (!isIssueOrPullRequestStateResponse(body)) {
1684
+ throw new Error(
1685
+ `Unexpected response shape when fetching state for ${url}`,
1686
+ );
1687
+ }
1688
+ return { state: body.state, merged: false, isPullRequest: false };
1689
+ };
1690
+
1691
+ getPullRequestSummary = async (
1692
+ prUrl: string,
1693
+ ): Promise<{
1694
+ title: string;
1695
+ body: string;
1696
+ additions: number;
1697
+ deletions: number;
1698
+ changedFiles: number;
1699
+ } | null> => {
1700
+ const {
1701
+ owner,
1702
+ repo,
1703
+ issueNumber: prNumber,
1704
+ isPr,
1705
+ } = this.parseIssueUrl(prUrl);
1706
+ if (!isPr) {
1707
+ return null;
1708
+ }
1709
+ const response = await fetch(
1710
+ `https://api.github.com/repos/${owner}/${repo}/pulls/${prNumber}`,
1711
+ {
1712
+ method: 'GET',
1713
+ headers: {
1714
+ Authorization: `Bearer ${this.ghToken}`,
1715
+ Accept: 'application/vnd.github+json',
1716
+ },
1717
+ },
1718
+ );
1719
+ if (!response.ok) {
1720
+ throw new Error(
1721
+ `Failed to fetch summary for PR ${prUrl}: HTTP ${response.status}`,
1722
+ );
1723
+ }
1724
+ const body: unknown = await response.json();
1725
+ if (!isPullRequestDetailResponse(body)) {
1726
+ throw new Error(
1727
+ `Unexpected response shape when fetching summary for PR ${prUrl}`,
1728
+ );
1729
+ }
1730
+ return {
1731
+ title: body.title,
1732
+ body: body.body ?? '',
1733
+ additions: body.additions,
1734
+ deletions: body.deletions,
1735
+ changedFiles: body.changed_files,
1736
+ };
1737
+ };
1246
1738
  }
@@ -16,6 +16,41 @@ export type RelatedPullRequest = {
16
16
  missingRequiredCheckNames: string[];
17
17
  };
18
18
 
19
+ export type IssueComment = {
20
+ author: string;
21
+ body: string;
22
+ createdAt: Date;
23
+ };
24
+
25
+ export type PullRequestFile = {
26
+ filename: string;
27
+ status: string;
28
+ additions: number;
29
+ deletions: number;
30
+ patch: string | null;
31
+ };
32
+
33
+ export type PullRequestDetail = {
34
+ title: string;
35
+ state: string;
36
+ merged: boolean;
37
+ isDraft: boolean;
38
+ additions: number;
39
+ deletions: number;
40
+ changedFiles: number;
41
+ headRefName: string;
42
+ baseRefName: string;
43
+ author: string;
44
+ files: PullRequestFile[];
45
+ };
46
+
47
+ export type PullRequestCommit = {
48
+ sha: string;
49
+ message: string;
50
+ author: string;
51
+ authoredAt: Date;
52
+ };
53
+
19
54
  export interface IssueRepository {
20
55
  getAllIssues: (
21
56
  projectId: Project['id'],
@@ -117,4 +152,20 @@ export interface IssueRepository {
117
152
  project: Project,
118
153
  issueUrl: string,
119
154
  ) => Promise<void>;
155
+ getIssueOrPullRequestBody: (url: string) => Promise<string>;
156
+ getIssueOrPullRequestComments: (url: string) => Promise<IssueComment[]>;
157
+ getPullRequestDetail: (prUrl: string) => Promise<PullRequestDetail | null>;
158
+ getPullRequestCommits: (prUrl: string) => Promise<PullRequestCommit[]>;
159
+ getIssueOrPullRequestState: (url: string) => Promise<{
160
+ state: string;
161
+ merged: boolean;
162
+ isPullRequest: boolean;
163
+ }>;
164
+ getPullRequestSummary: (prUrl: string) => Promise<{
165
+ title: string;
166
+ body: string;
167
+ additions: number;
168
+ deletions: number;
169
+ changedFiles: number;
170
+ } | null>;
120
171
  }
@@ -1,7 +1,13 @@
1
1
  {
2
2
  "extends": "./tsconfig.json",
3
3
  "include": ["src"],
4
- "exclude": ["node_modules", "**/__tests__/*", "**/*.test.ts"],
4
+ "exclude": [
5
+ "node_modules",
6
+ "**/__tests__/*",
7
+ "**/*.test.ts",
8
+ "src/adapter/entry-points/console/ui/**",
9
+ "src/adapter/entry-points/console/ui-dist/**"
10
+ ],
5
11
  "compilerOptions": {
6
12
  "rootDir": "./src",
7
13
  "outDir": "bin",
package/tsconfig.json CHANGED
@@ -20,5 +20,10 @@
20
20
  "types": ["jest", "node"]
21
21
  },
22
22
  "include": ["src"],
23
- "exclude": ["node_modules", "**/__tests__/*"]
23
+ "exclude": [
24
+ "node_modules",
25
+ "**/__tests__/*",
26
+ "src/adapter/entry-points/console/ui/**",
27
+ "src/adapter/entry-points/console/ui-dist/**"
28
+ ]
24
29
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/cli/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EACL,UAAU,EACV,cAAc,EACd,wBAAwB,EACxB,YAAY,EACZ,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AAqEzB,eAAO,MAAM,OAAO,SAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/cli/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EACL,UAAU,EACV,cAAc,EACd,wBAAwB,EACxB,YAAY,EACZ,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AAgFzB,eAAO,MAAM,OAAO,SAAgB,CAAC"}
@@ -18,6 +18,7 @@ export type ConfigFile = {
18
18
  awLogStaleThresholdMinutes?: number;
19
19
  labelsAsLlmAgentName?: string[];
20
20
  changeTargetPathAliases?: Record<string, string>;
21
+ consoleAccessToken?: string;
21
22
  };
22
23
  export declare const isRecord: (value: unknown) => value is Record<string, unknown>;
23
24
  export declare const loadConfigFile: (configFilePath: string) => ConfigFile;
@@ -1 +1 @@
1
- {"version":3,"file":"projectConfig.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/cli/projectConfig.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,UAAU,GAAG;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,8BAA8B,CAAC,EAAE,MAAM,CAAC;IACxC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,iCAAiC,CAAC,EAAE,MAAM,CAAC;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8BAA8B,CAAC,EAAE,MAAM,CAAC;IACxC,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,gCAAgC,CAAC,EAAE,MAAM,CAAC;IAC1C,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,uBAAuB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClD,CAAC;AAsDF,eAAO,MAAM,QAAQ,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CACH,CAAC;AAqBvE,eAAO,MAAM,cAAc,GAAI,gBAAgB,MAAM,KAAG,UAwDvD,CAAC;AAEF,eAAO,MAAM,wBAAwB,GACnC,QAAQ,MAAM,EACd,aAAa,MAAM,KAClB,UAoEF,CAAC;AAEF,eAAO,MAAM,YAAY,GACvB,YAAY,UAAU,EACtB,cAAc,UAAU,EACxB,iBAAiB,UAAU,KAC1B,UAuED,CAAC;AAkBH,eAAO,MAAM,kBAAkB,GAC7B,YAAY,MAAM,EAClB,OAAO,MAAM,KACZ,OAAO,CAAC,MAAM,GAAG,IAAI,CA0DvB,CAAC"}
1
+ {"version":3,"file":"projectConfig.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/cli/projectConfig.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,UAAU,GAAG;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,8BAA8B,CAAC,EAAE,MAAM,CAAC;IACxC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,iCAAiC,CAAC,EAAE,MAAM,CAAC;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8BAA8B,CAAC,EAAE,MAAM,CAAC;IACxC,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,gCAAgC,CAAC,EAAE,MAAM,CAAC;IAC1C,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,uBAAuB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjD,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAsDF,eAAO,MAAM,QAAQ,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CACH,CAAC;AAqBvE,eAAO,MAAM,cAAc,GAAI,gBAAgB,MAAM,KAAG,UAyDvD,CAAC;AAEF,eAAO,MAAM,wBAAwB,GACnC,QAAQ,MAAM,EACd,aAAa,MAAM,KAClB,UAoEF,CAAC;AAEF,eAAO,MAAM,YAAY,GACvB,YAAY,UAAU,EACtB,cAAc,UAAU,EACxB,iBAAiB,UAAU,KAC1B,UAyED,CAAC;AAkBH,eAAO,MAAM,kBAAkB,GAC7B,YAAY,MAAM,EAClB,OAAO,MAAM,KACZ,OAAO,CAAC,MAAM,GAAG,IAAI,CA0DvB,CAAC"}
@@ -0,0 +1,19 @@
1
+ import * as http from 'http';
2
+ export declare const DEFAULT_CONSOLE_PORT = 9981;
3
+ export declare const CONSOLE_TOKEN_HEADER = "x-pv-token";
4
+ export declare const hasDotSegment: (requestPath: string) => boolean;
5
+ export declare const requiresToken: (requestPath: string) => boolean;
6
+ export declare const isTokenValid: (expectedToken: string, providedToken: string | null) => boolean;
7
+ export declare const extractProvidedToken: (queryToken: string | string[] | null, headerToken: string | string[] | undefined) => string | null;
8
+ export type ConsoleServerOptions = {
9
+ accessToken: string;
10
+ uiDistDir: string;
11
+ consoleDataOutputDir: string | null;
12
+ };
13
+ export declare const handleConsoleRequest: (options: ConsoleServerOptions, request: http.IncomingMessage, response: http.ServerResponse) => void;
14
+ export declare const createConsoleServer: (options: ConsoleServerOptions) => http.Server;
15
+ export type StartConsoleServerOptions = ConsoleServerOptions & {
16
+ port: number;
17
+ };
18
+ export declare const startConsoleServer: (options: StartConsoleServerOptions) => Promise<http.Server>;
19
+ //# sourceMappingURL=consoleServer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consoleServer.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/console/consoleServer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAI7B,eAAO,MAAM,oBAAoB,OAAO,CAAC;AAEzC,eAAO,MAAM,oBAAoB,eAAe,CAAC;AAmCjD,eAAO,MAAM,aAAa,GAAI,aAAa,MAAM,KAAG,OAGiB,CAAC;AAEtE,eAAO,MAAM,aAAa,GAAI,aAAa,MAAM,KAAG,OAGrB,CAAC;AAEhC,eAAO,MAAM,YAAY,GACvB,eAAe,MAAM,EACrB,eAAe,MAAM,GAAG,IAAI,KAC3B,OAAoE,CAAC;AAExE,eAAO,MAAM,oBAAoB,GAC/B,YAAY,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,EACpC,aAAa,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,KACzC,MAAM,GAAG,IAQX,CAAC;AAuCF,MAAM,MAAM,oBAAoB,GAAG;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC,CAAC;AA0BF,eAAO,MAAM,oBAAoB,GAC/B,SAAS,oBAAoB,EAC7B,SAAS,IAAI,CAAC,eAAe,EAC7B,UAAU,IAAI,CAAC,cAAc,KAC5B,IAwDF,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAC9B,SAAS,oBAAoB,KAC5B,IAAI,CAAC,MAGJ,CAAC;AAEL,MAAM,MAAM,yBAAyB,GAAG,oBAAoB,GAAG;IAC7D,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAC7B,SAAS,yBAAyB,KACjC,OAAO,CAAC,IAAI,CAAC,MAAM,CAQlB,CAAC"}
@@ -1,4 +1,4 @@
1
- import { IssueRepository, RelatedPullRequest } from '../../../domain/usecases/adapter-interfaces/IssueRepository';
1
+ import { IssueRepository, RelatedPullRequest, IssueComment, PullRequestDetail, PullRequestCommit } from '../../../domain/usecases/adapter-interfaces/IssueRepository';
2
2
  import { Project } from '../../../domain/entities/Project';
3
3
  import { Issue } from '../../../domain/entities/Issue';
4
4
  import { StoryObjectMap } from '../../../domain/entities/StoryObjectMap';
@@ -70,5 +70,22 @@ export declare class ApiV3CheerioRestIssueRepository extends BaseGitHubRepositor
70
70
  requestChangesWithInlineComment: (prUrl: string, changedFilePath: string | null, commentBody: string) => Promise<void>;
71
71
  deletePullRequestBranch: (prUrl: string, branchName: string) => Promise<void>;
72
72
  createCommentByUrl: (issueOrPrUrl: string, commentBody: string) => Promise<void>;
73
+ getIssueOrPullRequestBody: (url: string) => Promise<string>;
74
+ getIssueOrPullRequestComments: (url: string) => Promise<IssueComment[]>;
75
+ getPullRequestDetail: (prUrl: string) => Promise<PullRequestDetail | null>;
76
+ private fetchPullRequestFiles;
77
+ getPullRequestCommits: (prUrl: string) => Promise<PullRequestCommit[]>;
78
+ getIssueOrPullRequestState: (url: string) => Promise<{
79
+ state: string;
80
+ merged: boolean;
81
+ isPullRequest: boolean;
82
+ }>;
83
+ getPullRequestSummary: (prUrl: string) => Promise<{
84
+ title: string;
85
+ body: string;
86
+ additions: number;
87
+ deletions: number;
88
+ changedFiles: number;
89
+ } | null>;
73
90
  }
74
91
  //# sourceMappingURL=ApiV3CheerioRestIssueRepository.d.ts.map