@gitkraken/core-gitlens 0.5.109 → 0.5.110
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.
- package/CHANGELOG.md +33 -1
- package/dist/git/models/pullRequest.d.ts +81 -0
- package/dist/git/models/pullRequest.d.ts.map +1 -1
- package/dist/git/models/pullRequest.js +15 -0
- package/dist/git/models/pullRequest.js.map +1 -1
- package/dist/git/utils/pullRequest.utils.d.ts +11 -1
- package/dist/git/utils/pullRequest.utils.d.ts.map +1 -1
- package/dist/git/utils/pullRequest.utils.js +40 -0
- package/dist/git/utils/pullRequest.utils.js.map +1 -1
- package/dist/plus/git-github/api/github.d.ts +37 -4
- package/dist/plus/git-github/api/github.d.ts.map +1 -1
- package/dist/plus/git-github/api/github.js +147 -16
- package/dist/plus/git-github/api/github.js.map +1 -1
- package/dist/plus/git-github/api/pullRequestSearchQuery.d.ts +27 -1
- package/dist/plus/git-github/api/pullRequestSearchQuery.d.ts.map +1 -1
- package/dist/plus/git-github/api/pullRequestSearchQuery.js +73 -6
- package/dist/plus/git-github/api/pullRequestSearchQuery.js.map +1 -1
- package/dist/plus/git-github/models.d.ts +17 -5
- package/dist/plus/git-github/models.d.ts.map +1 -1
- package/dist/plus/git-github/models.js +14 -1
- package/dist/plus/git-github/models.js.map +1 -1
- package/dist/plus/integrations/integrationService.d.ts +16 -1
- package/dist/plus/integrations/integrationService.d.ts.map +1 -1
- package/dist/plus/integrations/integrationService.js +9 -1
- package/dist/plus/integrations/integrationService.js.map +1 -1
- package/dist/plus/integrations/manager.d.ts +45 -5
- package/dist/plus/integrations/manager.d.ts.map +1 -1
- package/dist/plus/integrations/models/gitHostIntegration.d.ts +12 -0
- package/dist/plus/integrations/models/gitHostIntegration.d.ts.map +1 -1
- package/dist/plus/integrations/models/gitHostIntegration.js +18 -0
- package/dist/plus/integrations/models/gitHostIntegration.js.map +1 -1
- package/dist/plus/integrations/models/integration.d.ts +1 -1
- package/dist/plus/integrations/models/integration.d.ts.map +1 -1
- package/dist/plus/integrations/models/integration.js.map +1 -1
- package/dist/plus/integrations/providerFilters.d.ts +1 -1
- package/dist/plus/integrations/providerFilters.d.ts.map +1 -1
- package/dist/plus/integrations/providers/accounts.d.ts +6 -0
- package/dist/plus/integrations/providers/accounts.d.ts.map +1 -0
- package/dist/plus/integrations/providers/accounts.js +30 -0
- package/dist/plus/integrations/providers/accounts.js.map +1 -0
- package/dist/plus/integrations/providers/github.d.ts +9 -0
- package/dist/plus/integrations/providers/github.d.ts.map +1 -1
- package/dist/plus/integrations/providers/github.js +114 -135
- package/dist/plus/integrations/providers/github.js.map +1 -1
- package/dist/plus/integrations/providers/gitlab.d.ts +9 -0
- package/dist/plus/integrations/providers/gitlab.d.ts.map +1 -1
- package/dist/plus/integrations/providers/gitlab.js +23 -4
- package/dist/plus/integrations/providers/gitlab.js.map +1 -1
- package/dist/plus/integrations/providers/models.d.ts +14 -32
- package/dist/plus/integrations/providers/models.d.ts.map +1 -1
- package/dist/plus/integrations/providers/models.js +36 -105
- package/dist/plus/integrations/providers/models.js.map +1 -1
- package/dist/plus/integrations/providers/pullRequestReviews.d.ts +50 -0
- package/dist/plus/integrations/providers/pullRequestReviews.d.ts.map +1 -0
- package/dist/plus/integrations/providers/pullRequestReviews.js +99 -0
- package/dist/plus/integrations/providers/pullRequestReviews.js.map +1 -0
- package/dist/plus/integrations/reads/counts.d.ts +55 -0
- package/dist/plus/integrations/reads/counts.d.ts.map +1 -1
- package/dist/plus/integrations/reads/counts.js +146 -2
- package/dist/plus/integrations/reads/counts.js.map +1 -1
- package/dist/plus/integrations/reads/drains.d.ts +7 -1
- package/dist/plus/integrations/reads/drains.d.ts.map +1 -1
- package/dist/plus/integrations/reads/drains.js +13 -2
- package/dist/plus/integrations/reads/drains.js.map +1 -1
- package/dist/plus/integrations/reads/filters.d.ts.map +1 -1
- package/dist/plus/integrations/reads/filters.js +22 -0
- package/dist/plus/integrations/reads/filters.js.map +1 -1
- package/dist/plus/integrations/reads/searchPullRequests.d.ts +4 -3
- package/dist/plus/integrations/reads/searchPullRequests.d.ts.map +1 -1
- package/dist/plus/integrations/reads/searchPullRequests.js +6 -4
- package/dist/plus/integrations/reads/searchPullRequests.js.map +1 -1
- package/dist/plus/integrations/reads/sweeps.js +1 -1
- package/dist/plus/integrations/reads/sweeps.js.map +1 -1
- package/dist/plus/integrations/reads/warnings.d.ts +2 -2
- package/dist/plus/integrations/reads/warnings.d.ts.map +1 -1
- package/dist/plus/integrations/reads/warnings.js +11 -2
- package/dist/plus/integrations/reads/warnings.js.map +1 -1
- package/dist/plus/integrations/results.d.ts +6 -1
- package/dist/plus/integrations/results.d.ts.map +1 -1
- package/dist/plus/integrations/results.js.map +1 -1
- package/docs/integrations.md +76 -10
- package/docs/kepler-read-api-parity.md +9 -0
- package/package.json +1 -1
- package/src/git/models/pullRequest.ts +84 -0
- package/src/git/utils/pullRequest.utils.ts +50 -0
- package/src/plus/git-github/api/github.ts +176 -16
- package/src/plus/git-github/api/pullRequestSearchQuery.ts +81 -7
- package/src/plus/git-github/models.ts +29 -5
- package/src/plus/integrations/integrationService.ts +25 -2
- package/src/plus/integrations/manager.ts +50 -5
- package/src/plus/integrations/models/gitHostIntegration.ts +29 -0
- package/src/plus/integrations/models/integration.ts +1 -0
- package/src/plus/integrations/providerFilters.ts +6 -1
- package/src/plus/integrations/providers/accounts.ts +34 -0
- package/src/plus/integrations/providers/github.ts +133 -144
- package/src/plus/integrations/providers/gitlab.ts +28 -10
- package/src/plus/integrations/providers/models.ts +64 -124
- package/src/plus/integrations/providers/pullRequestReviews.ts +122 -0
- package/src/plus/integrations/reads/counts.ts +273 -2
- package/src/plus/integrations/reads/drains.ts +12 -2
- package/src/plus/integrations/reads/filters.ts +22 -0
- package/src/plus/integrations/reads/searchPullRequests.ts +12 -4
- package/src/plus/integrations/reads/sweeps.ts +1 -1
- package/src/plus/integrations/reads/warnings.ts +12 -1
- package/src/plus/integrations/results.ts +6 -1
|
@@ -41,26 +41,22 @@ import type {
|
|
|
41
41
|
SetPullRequestInput,
|
|
42
42
|
Trello,
|
|
43
43
|
} from '@gitkraken/provider-apis';
|
|
44
|
-
import
|
|
45
|
-
import
|
|
44
|
+
import { EntityIdentifierUtils } from '@gitkraken/provider-apis/entity-identifiers';
|
|
45
|
+
import { GitProviderUtils } from '@gitkraken/provider-apis/provider-utils';
|
|
46
46
|
import { githubSearchResultLimit } from '../../git-github/api/config.js';
|
|
47
47
|
import type { Account as UserAccount } from '../../../git/models/author.js';
|
|
48
|
-
import type {
|
|
48
|
+
import type { IssueProject, IssueShape, IssueStateFilter } from '../../../git/models/issue.js';
|
|
49
49
|
import { Issue, RepositoryAccessLevel } from '../../../git/models/issue.js';
|
|
50
50
|
import type {
|
|
51
|
-
PullRequestMember,
|
|
52
51
|
PullRequestRef,
|
|
53
52
|
PullRequestRefs,
|
|
54
53
|
PullRequestRepositoryIdentityDescriptor,
|
|
55
|
-
PullRequestReviewer,
|
|
56
54
|
PullRequestState,
|
|
57
55
|
PullRequestStateFilter,
|
|
58
56
|
} from '../../../git/models/pullRequest.js';
|
|
59
57
|
import {
|
|
60
58
|
PullRequest,
|
|
61
59
|
PullRequestMergeableState,
|
|
62
|
-
PullRequestReviewDecision,
|
|
63
|
-
PullRequestReviewState,
|
|
64
60
|
PullRequestStatusCheckRollupState,
|
|
65
61
|
} from '../../../git/models/pullRequest.js';
|
|
66
62
|
import type { Provider, ProviderReference } from '../../../git/models/remoteProvider.js';
|
|
@@ -75,7 +71,12 @@ import {
|
|
|
75
71
|
IssuesCloudHostIntegrationId,
|
|
76
72
|
} from '../constants.js';
|
|
77
73
|
import type { Integration, IntegrationType } from '../models/integration.js';
|
|
78
|
-
import type {
|
|
74
|
+
import type {
|
|
75
|
+
IssueSearchCapabilities,
|
|
76
|
+
IssueSorting,
|
|
77
|
+
PullRequestSearchCapabilities,
|
|
78
|
+
PullRequestSorting,
|
|
79
|
+
} from '../providerFilters.js';
|
|
79
80
|
import { IssueFilter, PullRequestFilter } from '../providerFilters.js';
|
|
80
81
|
|
|
81
82
|
export { IssueFilter, PullRequestFilter } from '../providerFilters.js';
|
|
@@ -87,10 +88,13 @@ export type {
|
|
|
87
88
|
IssueSorting,
|
|
88
89
|
PullRequestSearchCapabilities,
|
|
89
90
|
PullRequestSearchCriteria,
|
|
91
|
+
PullRequestSortField,
|
|
92
|
+
PullRequestSorting,
|
|
90
93
|
} from '../providerFilters.js';
|
|
91
94
|
import type { ProviderRepositoryShape } from '../results.js';
|
|
92
95
|
|
|
93
96
|
export type { ProviderOrganization, ProviderRepositoryShape } from '../results.js';
|
|
97
|
+
import { fromProviderAccount, toProviderAccount } from './accounts.js';
|
|
94
98
|
import {
|
|
95
99
|
azureAccountWideIssueSorts,
|
|
96
100
|
azureIssueSorts,
|
|
@@ -102,6 +106,15 @@ import {
|
|
|
102
106
|
linearIssueSorts,
|
|
103
107
|
trelloIssueSorts,
|
|
104
108
|
} from './issueSorts.js';
|
|
109
|
+
import type { ProviderPullRequestReview, ProviderPullRequestReviews } from './pullRequestReviews.js';
|
|
110
|
+
import {
|
|
111
|
+
fromPullRequestReviewDecision,
|
|
112
|
+
providerPullRequestReviewStateDismissed,
|
|
113
|
+
toCompletedReviews,
|
|
114
|
+
toProviderReviewDecision,
|
|
115
|
+
toProviderReviews,
|
|
116
|
+
toReviewRequests,
|
|
117
|
+
} from './pullRequestReviews.js';
|
|
105
118
|
import { getEntityIdentifierInput } from './utils.js';
|
|
106
119
|
|
|
107
120
|
type GitBuildStatusState = GitBuildStatusStateType;
|
|
@@ -110,9 +123,6 @@ type GitPullRequestMergeableState = GitPullRequestMergeableStateType;
|
|
|
110
123
|
type GitPullRequestReviewState = GitPullRequestReviewStateType;
|
|
111
124
|
type GitPullRequestState = GitPullRequestStateType;
|
|
112
125
|
|
|
113
|
-
const { EntityIdentifierUtils } = entityIdentifiersModule;
|
|
114
|
-
const { GitProviderUtils } = providerUtilsModule;
|
|
115
|
-
|
|
116
126
|
// Local runtime copies of the `@gitkraken/provider-apis` string enums. Duplicated (not imported as
|
|
117
127
|
// values) because the SDK ships as CJS whose named enum exports can't be statically imported as ESM
|
|
118
128
|
// values from the bundled `dist`. Exported so the enum-parity test can deep-equal them against the
|
|
@@ -191,7 +201,7 @@ export function isRepoIdsInput(input: unknown): input is (string | number)[] {
|
|
|
191
201
|
);
|
|
192
202
|
}
|
|
193
203
|
|
|
194
|
-
export type ProviderPullRequest = GitPullRequest;
|
|
204
|
+
export type ProviderPullRequest = Omit<GitPullRequest, 'reviews'> & { reviews: ProviderPullRequestReviews };
|
|
195
205
|
export type ProviderRepository = GitRepository;
|
|
196
206
|
export type ProviderIssue = ProviderApiIssue;
|
|
197
207
|
export type ProviderEnterpriseOptions = EnterpriseOptions;
|
|
@@ -859,19 +869,36 @@ const githubIssueSearchCapabilities: IssueSearchCapabilities = {
|
|
|
859
869
|
sorts: githubIssueSorts,
|
|
860
870
|
};
|
|
861
871
|
|
|
872
|
+
/**
|
|
873
|
+
* The ordering vocabulary of GitHub's filtered PR search: `created` and `updated`, both directions.
|
|
874
|
+
*
|
|
875
|
+
* Hand-declared rather than derived from `@gitkraken/provider-apis` (which has no PR-sort surface), and narrower
|
|
876
|
+
* than the issue set on purpose: the merged relationship × state facets can only be re-ordered by a field a
|
|
877
|
+
* `PullRequestShape` carries (see `getPullRequestComparator`), and GitHub PRs have no priority and no relevance
|
|
878
|
+
* that orders stably under the result ceiling. A parity test pins this to `gitHubPullRequestSortQualifiers`' keys
|
|
879
|
+
* so the capability can't outrun the emitter.
|
|
880
|
+
*/
|
|
881
|
+
const githubPullRequestSorts: PullRequestSorting[] = ['updated:desc', 'updated:asc', 'created:desc', 'created:asc'];
|
|
882
|
+
|
|
862
883
|
/** GitHub and GHE use the same filtered pull-request search syntax and result ceiling. */
|
|
863
884
|
const githubPullRequestSearchCapabilities: PullRequestSearchCapabilities = {
|
|
864
885
|
relationships: [
|
|
865
886
|
PullRequestFilter.Author,
|
|
866
887
|
PullRequestFilter.Assignee,
|
|
867
888
|
PullRequestFilter.ReviewRequested,
|
|
889
|
+
PullRequestFilter.Reviewed,
|
|
868
890
|
PullRequestFilter.Mention,
|
|
869
891
|
],
|
|
870
892
|
states: ['open', 'closed', 'merged', 'all'],
|
|
871
893
|
text: true,
|
|
894
|
+
updatedAfter: true,
|
|
895
|
+
createdAfter: true,
|
|
872
896
|
includeArchived: true,
|
|
897
|
+
draft: true,
|
|
873
898
|
repositoryScope: true,
|
|
874
899
|
organizationScope: true,
|
|
900
|
+
// `sort:updated`, `sort:updated-asc`, `sort:created-desc`, `sort:created-asc` — see `githubPullRequestSorts`.
|
|
901
|
+
sorts: githubPullRequestSorts,
|
|
875
902
|
};
|
|
876
903
|
|
|
877
904
|
export const providersMetadata: ProvidersMetadata = {
|
|
@@ -894,6 +921,7 @@ export const providersMetadata: ProvidersMetadata = {
|
|
|
894
921
|
PullRequestFilter.Author,
|
|
895
922
|
PullRequestFilter.Assignee,
|
|
896
923
|
PullRequestFilter.ReviewRequested,
|
|
924
|
+
PullRequestFilter.Reviewed,
|
|
897
925
|
PullRequestFilter.Mention,
|
|
898
926
|
],
|
|
899
927
|
supportedPullRequestSearch: githubPullRequestSearchCapabilities,
|
|
@@ -930,6 +958,7 @@ export const providersMetadata: ProvidersMetadata = {
|
|
|
930
958
|
PullRequestFilter.Author,
|
|
931
959
|
PullRequestFilter.Assignee,
|
|
932
960
|
PullRequestFilter.ReviewRequested,
|
|
961
|
+
PullRequestFilter.Reviewed,
|
|
933
962
|
PullRequestFilter.Mention,
|
|
934
963
|
],
|
|
935
964
|
supportedPullRequestSearch: githubPullRequestSearchCapabilities,
|
|
@@ -1320,22 +1349,6 @@ export const fromProviderBuildStatusState = {
|
|
|
1320
1349
|
[GitBuildStatusState.Warning]: undefined,
|
|
1321
1350
|
};
|
|
1322
1351
|
|
|
1323
|
-
export const toProviderPullRequestReviewState = {
|
|
1324
|
-
[PullRequestReviewState.Approved]: GitPullRequestReviewState.Approved,
|
|
1325
|
-
[PullRequestReviewState.ChangesRequested]: GitPullRequestReviewState.ChangesRequested,
|
|
1326
|
-
[PullRequestReviewState.Commented]: GitPullRequestReviewState.Commented,
|
|
1327
|
-
[PullRequestReviewState.ReviewRequested]: GitPullRequestReviewState.ReviewRequested,
|
|
1328
|
-
[PullRequestReviewState.Dismissed]: null,
|
|
1329
|
-
[PullRequestReviewState.Pending]: null,
|
|
1330
|
-
};
|
|
1331
|
-
|
|
1332
|
-
export const fromProviderPullRequestReviewState = {
|
|
1333
|
-
[GitPullRequestReviewState.Approved]: PullRequestReviewState.Approved,
|
|
1334
|
-
[GitPullRequestReviewState.ChangesRequested]: PullRequestReviewState.ChangesRequested,
|
|
1335
|
-
[GitPullRequestReviewState.Commented]: PullRequestReviewState.Commented,
|
|
1336
|
-
[GitPullRequestReviewState.ReviewRequested]: PullRequestReviewState.ReviewRequested,
|
|
1337
|
-
};
|
|
1338
|
-
|
|
1339
1352
|
export const toProviderPullRequestMergeableState = {
|
|
1340
1353
|
[PullRequestMergeableState.Mergeable]: GitPullRequestMergeableState.Mergeable,
|
|
1341
1354
|
[PullRequestMergeableState.Conflicting]: GitPullRequestMergeableState.Conflicts,
|
|
@@ -1355,68 +1368,6 @@ export const fromProviderPullRequestMergeableState = {
|
|
|
1355
1368
|
[GitPullRequestMergeableState.Unstable]: PullRequestMergeableState.Unknown,
|
|
1356
1369
|
};
|
|
1357
1370
|
|
|
1358
|
-
export function toProviderReviews(reviewers: PullRequestReviewer[]): ProviderPullRequest['reviews'] {
|
|
1359
|
-
return reviewers
|
|
1360
|
-
.filter(r => r.state !== PullRequestReviewState.Dismissed && r.state !== PullRequestReviewState.Pending)
|
|
1361
|
-
.map(reviewer => ({
|
|
1362
|
-
reviewer: toProviderAccount(reviewer.reviewer),
|
|
1363
|
-
state: toProviderPullRequestReviewState[reviewer.state] ?? GitPullRequestReviewState.ReviewRequested,
|
|
1364
|
-
}));
|
|
1365
|
-
}
|
|
1366
|
-
|
|
1367
|
-
export function toReviewRequests(reviews: ProviderPullRequest['reviews']): PullRequestReviewer[] | undefined {
|
|
1368
|
-
return reviews == null
|
|
1369
|
-
? undefined
|
|
1370
|
-
: reviews
|
|
1371
|
-
?.filter(r => r.state === GitPullRequestReviewState.ReviewRequested)
|
|
1372
|
-
.map(r => ({
|
|
1373
|
-
isCodeOwner: false, // TODO: Find this value, and implement in the shared lib if needed
|
|
1374
|
-
reviewer: fromProviderAccount(r.reviewer),
|
|
1375
|
-
state: PullRequestReviewState.ReviewRequested,
|
|
1376
|
-
}));
|
|
1377
|
-
}
|
|
1378
|
-
|
|
1379
|
-
export function toCompletedReviews(reviews: ProviderPullRequest['reviews']): PullRequestReviewer[] | undefined {
|
|
1380
|
-
return reviews == null
|
|
1381
|
-
? undefined
|
|
1382
|
-
: reviews
|
|
1383
|
-
?.filter(r => r.state !== GitPullRequestReviewState.ReviewRequested)
|
|
1384
|
-
.map(r => ({
|
|
1385
|
-
isCodeOwner: false, // TODO: Find this value, and implement in the shared lib if needed
|
|
1386
|
-
reviewer: fromProviderAccount(r.reviewer),
|
|
1387
|
-
state: fromProviderPullRequestReviewState[r.state],
|
|
1388
|
-
}));
|
|
1389
|
-
}
|
|
1390
|
-
|
|
1391
|
-
export function toProviderReviewDecision(
|
|
1392
|
-
reviewDecision?: PullRequestReviewDecision,
|
|
1393
|
-
reviewers?: PullRequestReviewer[],
|
|
1394
|
-
): GitPullRequestReviewState | null {
|
|
1395
|
-
switch (reviewDecision) {
|
|
1396
|
-
case PullRequestReviewDecision.Approved:
|
|
1397
|
-
return GitPullRequestReviewState.Approved;
|
|
1398
|
-
case PullRequestReviewDecision.ChangesRequested:
|
|
1399
|
-
return GitPullRequestReviewState.ChangesRequested;
|
|
1400
|
-
case PullRequestReviewDecision.ReviewRequired:
|
|
1401
|
-
return GitPullRequestReviewState.ReviewRequested;
|
|
1402
|
-
default: {
|
|
1403
|
-
if (reviewers?.some(r => r.state === PullRequestReviewState.ReviewRequested)) {
|
|
1404
|
-
return GitPullRequestReviewState.ReviewRequested;
|
|
1405
|
-
} else if (reviewers?.some(r => r.state === PullRequestReviewState.Commented)) {
|
|
1406
|
-
return GitPullRequestReviewState.Commented;
|
|
1407
|
-
}
|
|
1408
|
-
return null;
|
|
1409
|
-
}
|
|
1410
|
-
}
|
|
1411
|
-
}
|
|
1412
|
-
|
|
1413
|
-
export const fromPullRequestReviewDecision = {
|
|
1414
|
-
[GitPullRequestReviewState.Approved]: PullRequestReviewDecision.Approved,
|
|
1415
|
-
[GitPullRequestReviewState.ChangesRequested]: PullRequestReviewDecision.ChangesRequested,
|
|
1416
|
-
[GitPullRequestReviewState.Commented]: undefined,
|
|
1417
|
-
[GitPullRequestReviewState.ReviewRequested]: PullRequestReviewDecision.ReviewRequired,
|
|
1418
|
-
};
|
|
1419
|
-
|
|
1420
1371
|
export function toProviderPullRequestState(state: PullRequestState): GitPullRequestState {
|
|
1421
1372
|
return state === 'opened'
|
|
1422
1373
|
? GitPullRequestState.Open
|
|
@@ -1541,7 +1492,11 @@ export function toProviderPullRequest(pr: PullRequest): ProviderPullRequest {
|
|
|
1541
1492
|
name: pr.refs.head.branch,
|
|
1542
1493
|
oid: pr.refs.head.sha,
|
|
1543
1494
|
},
|
|
1544
|
-
|
|
1495
|
+
// `null` when the source carried no review data at all, rather than the empty array a lite read would
|
|
1496
|
+
// otherwise produce: `toCompletedReviews`/`toReviewRequests` map `null` back to `undefined`, which is what
|
|
1497
|
+
// lets a consumer tell "nobody has reviewed this" from "this read never fetched reviews" (see
|
|
1498
|
+
// `PullRequestShape.latestReviews`). An empty array from a full projection stays an empty array.
|
|
1499
|
+
reviews: pr.reviewRequests == null && pr.latestReviews == null ? null : toProviderReviews(prReviews),
|
|
1545
1500
|
reviewDecision: toProviderReviewDecision(pr.reviewDecision, prReviews),
|
|
1546
1501
|
repository:
|
|
1547
1502
|
pr.repository != null
|
|
@@ -1740,46 +1695,31 @@ export function fromProviderIssue(
|
|
|
1740
1695
|
}
|
|
1741
1696
|
|
|
1742
1697
|
export function toProviderPullRequestWithUniqueId(pr: PullRequest): PullRequestWithUniqueID {
|
|
1698
|
+
const { reviews, ...providerPr } = toProviderPullRequest(pr);
|
|
1743
1699
|
return {
|
|
1744
|
-
...
|
|
1700
|
+
...providerPr,
|
|
1701
|
+
// The SDK boundary: `getActionablePullRequests` categorizes by review state and only knows
|
|
1702
|
+
// provider-apis' own vocabulary, so the locally-added dismissed state is dropped here rather than
|
|
1703
|
+
// handed over as a value it would fall through on. Our own projection keeps it — see
|
|
1704
|
+
// `providerPullRequestReviewStateDismissed`. `commitOid` rides along on the surviving reviews: it is an
|
|
1705
|
+
// extra property the SDK ignores, not a value it could misread.
|
|
1706
|
+
reviews:
|
|
1707
|
+
reviews?.filter(
|
|
1708
|
+
(r): r is ProviderPullRequestReview & { state: GitPullRequestReviewState } =>
|
|
1709
|
+
r.state !== providerPullRequestReviewStateDismissed,
|
|
1710
|
+
) ?? null,
|
|
1745
1711
|
uuid: EntityIdentifierUtils.encode(getEntityIdentifierInput(pr)),
|
|
1746
1712
|
};
|
|
1747
1713
|
}
|
|
1748
1714
|
|
|
1749
|
-
export function toProviderAccount(account: PullRequestMember | IssueMember): ProviderAccount {
|
|
1750
|
-
return {
|
|
1751
|
-
id: account.id ?? null,
|
|
1752
|
-
avatarUrl: account.avatarUrl ?? null,
|
|
1753
|
-
name: account.name ?? null,
|
|
1754
|
-
url: account.url ?? null,
|
|
1755
|
-
// TODO: Implement these in our own model
|
|
1756
|
-
email: '',
|
|
1757
|
-
username: account.name ?? null,
|
|
1758
|
-
};
|
|
1759
|
-
}
|
|
1760
|
-
|
|
1761
|
-
export function fromProviderAccount(account: ProviderAccount | null): PullRequestMember | IssueMember {
|
|
1762
|
-
return {
|
|
1763
|
-
id: account?.id ?? '',
|
|
1764
|
-
// An absent name stays absent. `'unknown'` was a display fallback invented in the provider layer, and a
|
|
1765
|
-
// consumer couldn't tell it apart from a member genuinely named that — so it couldn't be undone where a
|
|
1766
|
-
// name-shaped placeholder is wrong (rendering an avatar-only chip, or building an AI prompt, where
|
|
1767
|
-
// `Assignees: unknown` reads as a real assignee). It also disagreed with {@link toIssueShape}, which
|
|
1768
|
-
// collapsed the same absent name to `''` — same facade method, two fallbacks. Both now emit `undefined`.
|
|
1769
|
-
name: account?.name ?? undefined,
|
|
1770
|
-
avatarUrl: account?.avatarUrl ?? undefined,
|
|
1771
|
-
// `url` is optional, so an absent one must be `undefined`, not `''`. `''` passes a `!= null` presence
|
|
1772
|
-
// check and renders as a link to nowhere, and it disagreed with {@link toIssueShape} — which already
|
|
1773
|
-
// collapses to `undefined` — even though BOTH mappers feed `listIssuesPage` (the repo-scoped path goes
|
|
1774
|
-
// through `toIssueShape`, Azure's account-wide path through {@link fromProviderIssue}). Same facade
|
|
1775
|
-
// method, two shapes. Matches {@link toProviderRepositoryShape}, which collapses every absent optional.
|
|
1776
|
-
url: account?.url ?? undefined,
|
|
1777
|
-
};
|
|
1778
|
-
}
|
|
1779
|
-
|
|
1780
1715
|
export type ProviderActionablePullRequest = ActionablePullRequest;
|
|
1781
1716
|
|
|
1782
|
-
|
|
1717
|
+
/**
|
|
1718
|
+
* Built on the SDK's `GitPullRequest`, NOT the local {@link ProviderPullRequest} widening: this is handed to
|
|
1719
|
+
* `getActionablePullRequests`, which categorizes by review state and only knows provider-apis' vocabulary.
|
|
1720
|
+
* {@link toProviderPullRequestWithUniqueId} is what narrows `reviews` down to it.
|
|
1721
|
+
*/
|
|
1722
|
+
export type EnrichablePullRequest = GitPullRequest & {
|
|
1783
1723
|
uuid: string;
|
|
1784
1724
|
type: 'pullrequest';
|
|
1785
1725
|
provider: ProviderReference;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import type { GitPullRequest } from '@gitkraken/provider-apis';
|
|
2
|
+
import { GitPullRequestReviewState } from '@gitkraken/provider-apis';
|
|
3
|
+
import type { PullRequestReviewer } from '../../../git/models/pullRequest.js';
|
|
4
|
+
import { PullRequestReviewDecision, PullRequestReviewState } from '../../../git/models/pullRequest.js';
|
|
5
|
+
import { fromProviderAccount, toProviderAccount } from './accounts.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The GitLens-local extension of provider-apis' review shape, in two parts: a `DISMISSED` state the upstream
|
|
9
|
+
* `GitPullRequestReviewState` has no member for, and the head-commit oid a review was submitted against
|
|
10
|
+
* (optional, so a raw SDK review stays assignable — only the GitHub path populates it).
|
|
11
|
+
*
|
|
12
|
+
* Both exist for the same case: on GitHub the `dismiss stale reviews` rule flips an approval to dismissed on
|
|
13
|
+
* the next push, which is exactly the "the PR moved past my review" situation the oid detects. Dropping such a
|
|
14
|
+
* review instead would hand a consumer a PR out of the `reviewed-by:@me` set with no review row at all,
|
|
15
|
+
* indistinguishable from never having reviewed it.
|
|
16
|
+
*/
|
|
17
|
+
export const providerPullRequestReviewStateDismissed = 'DISMISSED' as const;
|
|
18
|
+
export type ProviderPullRequestReview = Omit<NonNullable<GitPullRequest['reviews']>[number], 'state'> & {
|
|
19
|
+
state: GitPullRequestReviewState | typeof providerPullRequestReviewStateDismissed;
|
|
20
|
+
commitOid?: string;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* The review list as it travels on {@link ProviderPullRequest}: `null` when the read carried no review data at
|
|
24
|
+
* all, as opposed to an empty array for a pull request nobody has reviewed.
|
|
25
|
+
*/
|
|
26
|
+
export type ProviderPullRequestReviews = ProviderPullRequestReview[] | null;
|
|
27
|
+
|
|
28
|
+
export const toProviderPullRequestReviewState = {
|
|
29
|
+
[PullRequestReviewState.Approved]: GitPullRequestReviewState.Approved,
|
|
30
|
+
[PullRequestReviewState.ChangesRequested]: GitPullRequestReviewState.ChangesRequested,
|
|
31
|
+
[PullRequestReviewState.Commented]: GitPullRequestReviewState.Commented,
|
|
32
|
+
[PullRequestReviewState.ReviewRequested]: GitPullRequestReviewState.ReviewRequested,
|
|
33
|
+
[PullRequestReviewState.Dismissed]: providerPullRequestReviewStateDismissed,
|
|
34
|
+
// A review the author started but never submitted. Visible only to that author and carrying no verdict, so
|
|
35
|
+
// it stays unmapped and is dropped by the projection.
|
|
36
|
+
[PullRequestReviewState.Pending]: null,
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const fromProviderPullRequestReviewState = {
|
|
40
|
+
[GitPullRequestReviewState.Approved]: PullRequestReviewState.Approved,
|
|
41
|
+
[GitPullRequestReviewState.ChangesRequested]: PullRequestReviewState.ChangesRequested,
|
|
42
|
+
[GitPullRequestReviewState.Commented]: PullRequestReviewState.Commented,
|
|
43
|
+
[GitPullRequestReviewState.ReviewRequested]: PullRequestReviewState.ReviewRequested,
|
|
44
|
+
[providerPullRequestReviewStateDismissed]: PullRequestReviewState.Dismissed,
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export function toProviderReviews(reviewers: PullRequestReviewer[]): ProviderPullRequestReviews {
|
|
48
|
+
// Only `Pending` maps to null (see `toProviderPullRequestReviewState`), so this drops exactly the reviews
|
|
49
|
+
// that carry no verdict rather than defaulting them to `ReviewRequested` — which would report an unsubmitted
|
|
50
|
+
// draft as a pending request from that reviewer.
|
|
51
|
+
return reviewers
|
|
52
|
+
.filter(r => r.state !== PullRequestReviewState.Pending)
|
|
53
|
+
.map(reviewer => ({
|
|
54
|
+
reviewer: toProviderAccount(reviewer.reviewer),
|
|
55
|
+
state: toProviderPullRequestReviewState[reviewer.state] ?? GitPullRequestReviewState.ReviewRequested,
|
|
56
|
+
commitOid: reviewer.commitOid,
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function toReviewRequests(reviews: ProviderPullRequestReviews): PullRequestReviewer[] | undefined {
|
|
61
|
+
return reviews == null
|
|
62
|
+
? undefined
|
|
63
|
+
: reviews
|
|
64
|
+
?.filter(r => r.state === GitPullRequestReviewState.ReviewRequested)
|
|
65
|
+
.map(r => ({
|
|
66
|
+
isCodeOwner: false, // TODO: Find this value, and implement in the shared lib if needed
|
|
67
|
+
reviewer: fromProviderAccount(r.reviewer),
|
|
68
|
+
state: PullRequestReviewState.ReviewRequested,
|
|
69
|
+
}));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function toCompletedReviews(reviews: ProviderPullRequestReviews): PullRequestReviewer[] | undefined {
|
|
73
|
+
return reviews == null
|
|
74
|
+
? undefined
|
|
75
|
+
: reviews
|
|
76
|
+
?.filter(
|
|
77
|
+
r =>
|
|
78
|
+
r.state !== GitPullRequestReviewState.ReviewRequested &&
|
|
79
|
+
// provider-apis' own GitHub normalizer maps only its four known states, so a review it has no
|
|
80
|
+
// member for (a real `DISMISSED` one, which its `latestReviews(first: 100)` selection does
|
|
81
|
+
// return) arrives with `state: undefined` — a value its type says cannot happen. Publishing it
|
|
82
|
+
// would put an unswitchable state on `PullRequestShape.latestReviews`, and mapping back would
|
|
83
|
+
// hit `toProviderReviews`' fallback and report a dismissed review as an outstanding request.
|
|
84
|
+
// Our own GitHub path never lands here: it carries `providerPullRequestReviewStateDismissed`.
|
|
85
|
+
fromProviderPullRequestReviewState[r.state] != null,
|
|
86
|
+
)
|
|
87
|
+
.map(r => ({
|
|
88
|
+
isCodeOwner: false, // TODO: Find this value, and implement in the shared lib if needed
|
|
89
|
+
reviewer: fromProviderAccount(r.reviewer),
|
|
90
|
+
state: fromProviderPullRequestReviewState[r.state],
|
|
91
|
+
commitOid: r.commitOid,
|
|
92
|
+
}));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function toProviderReviewDecision(
|
|
96
|
+
reviewDecision?: PullRequestReviewDecision,
|
|
97
|
+
reviewers?: PullRequestReviewer[],
|
|
98
|
+
): GitPullRequestReviewState | null {
|
|
99
|
+
switch (reviewDecision) {
|
|
100
|
+
case PullRequestReviewDecision.Approved:
|
|
101
|
+
return GitPullRequestReviewState.Approved;
|
|
102
|
+
case PullRequestReviewDecision.ChangesRequested:
|
|
103
|
+
return GitPullRequestReviewState.ChangesRequested;
|
|
104
|
+
case PullRequestReviewDecision.ReviewRequired:
|
|
105
|
+
return GitPullRequestReviewState.ReviewRequested;
|
|
106
|
+
default: {
|
|
107
|
+
if (reviewers?.some(r => r.state === PullRequestReviewState.ReviewRequested)) {
|
|
108
|
+
return GitPullRequestReviewState.ReviewRequested;
|
|
109
|
+
} else if (reviewers?.some(r => r.state === PullRequestReviewState.Commented)) {
|
|
110
|
+
return GitPullRequestReviewState.Commented;
|
|
111
|
+
}
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export const fromPullRequestReviewDecision = {
|
|
118
|
+
[GitPullRequestReviewState.Approved]: PullRequestReviewDecision.Approved,
|
|
119
|
+
[GitPullRequestReviewState.ChangesRequested]: PullRequestReviewDecision.ChangesRequested,
|
|
120
|
+
[GitPullRequestReviewState.Commented]: undefined,
|
|
121
|
+
[GitPullRequestReviewState.ReviewRequested]: PullRequestReviewDecision.ReviewRequired,
|
|
122
|
+
};
|