@gitkraken/core-gitlens 0.9.3 → 0.9.5
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 +34 -1
- package/dist/git/models/issue.d.ts +25 -2
- package/dist/git/models/issue.js +3 -1
- package/dist/git/models/issue.js.map +1 -1
- package/dist/git/models/pullRequest.d.ts +55 -5
- package/dist/git/models/pullRequest.js +5 -1
- package/dist/git/models/pullRequest.js.map +1 -1
- package/dist/git/utils/issue.utils.d.ts +4 -0
- package/dist/git/utils/issue.utils.js +4 -0
- package/dist/git/utils/issue.utils.js.map +1 -1
- package/dist/git/utils/pullRequest.utils.d.ts +4 -0
- package/dist/git/utils/pullRequest.utils.js +8 -0
- package/dist/git/utils/pullRequest.utils.js.map +1 -1
- package/dist/plus/git-github/api/github.d.ts +64 -4
- package/dist/plus/git-github/api/github.js +232 -15
- package/dist/plus/git-github/api/github.js.map +1 -1
- package/dist/plus/git-github/models.d.ts +48 -6
- package/dist/plus/git-github/models.js +11 -10
- package/dist/plus/git-github/models.js.map +1 -1
- package/dist/plus/integrations/fieldPresence.d.ts +75 -0
- package/dist/plus/integrations/fieldPresence.js +381 -0
- package/dist/plus/integrations/fieldPresence.js.map +1 -0
- package/dist/plus/integrations/index.d.ts +6 -4
- package/dist/plus/integrations/index.js +2 -1
- package/dist/plus/integrations/index.js.map +1 -1
- package/dist/plus/integrations/integrationService.d.ts +13 -4
- package/dist/plus/integrations/integrationService.js.map +1 -1
- package/dist/plus/integrations/manager.d.ts +62 -7
- package/dist/plus/integrations/models/gitHostIntegration.d.ts +103 -9
- package/dist/plus/integrations/models/gitHostIntegration.js +116 -5
- package/dist/plus/integrations/models/gitHostIntegration.js.map +1 -1
- package/dist/plus/integrations/models/integration.d.ts +91 -4
- package/dist/plus/integrations/models/integration.js +56 -7
- package/dist/plus/integrations/models/integration.js.map +1 -1
- package/dist/plus/integrations/models/issueReads.d.ts +14 -0
- package/dist/plus/integrations/models/issuesIntegration.d.ts +44 -3
- package/dist/plus/integrations/models/issuesIntegration.js +51 -1
- package/dist/plus/integrations/models/issuesIntegration.js.map +1 -1
- package/dist/plus/integrations/providers/azure/azure.js +3 -3
- package/dist/plus/integrations/providers/azure/azure.js.map +1 -1
- package/dist/plus/integrations/providers/azure/models.d.ts +36 -4
- package/dist/plus/integrations/providers/azure/models.js +118 -8
- package/dist/plus/integrations/providers/azure/models.js.map +1 -1
- package/dist/plus/integrations/providers/azureDevOps.d.ts +102 -5
- package/dist/plus/integrations/providers/azureDevOps.js +264 -45
- package/dist/plus/integrations/providers/azureDevOps.js.map +1 -1
- package/dist/plus/integrations/providers/azureDevOpsServer.d.ts +30 -6
- package/dist/plus/integrations/providers/azureDevOpsServer.js +82 -21
- package/dist/plus/integrations/providers/azureDevOpsServer.js.map +1 -1
- package/dist/plus/integrations/providers/bitbucket/bitbucket.d.ts +21 -1
- package/dist/plus/integrations/providers/bitbucket/bitbucket.js +74 -10
- package/dist/plus/integrations/providers/bitbucket/bitbucket.js.map +1 -1
- package/dist/plus/integrations/providers/bitbucket/models.d.ts +45 -8
- package/dist/plus/integrations/providers/bitbucket/models.js +32 -9
- package/dist/plus/integrations/providers/bitbucket/models.js.map +1 -1
- package/dist/plus/integrations/providers/bitbucket-server/models.d.ts +2 -6
- package/dist/plus/integrations/providers/bitbucket-server/models.js +1 -3
- package/dist/plus/integrations/providers/bitbucket-server/models.js.map +1 -1
- package/dist/plus/integrations/providers/bitbucket-server/pullRequestSearch.d.ts +3 -1
- package/dist/plus/integrations/providers/bitbucket-server/pullRequestSearch.js +4 -1
- package/dist/plus/integrations/providers/bitbucket-server/pullRequestSearch.js.map +1 -1
- package/dist/plus/integrations/providers/bitbucket-server.d.ts +2 -2
- package/dist/plus/integrations/providers/bitbucket-server.js +7 -5
- package/dist/plus/integrations/providers/bitbucket-server.js.map +1 -1
- package/dist/plus/integrations/providers/bitbucket.d.ts +22 -2
- package/dist/plus/integrations/providers/bitbucket.js +29 -6
- package/dist/plus/integrations/providers/bitbucket.js.map +1 -1
- package/dist/plus/integrations/providers/github.d.ts +40 -3
- package/dist/plus/integrations/providers/github.js +133 -11
- package/dist/plus/integrations/providers/github.js.map +1 -1
- package/dist/plus/integrations/providers/gitlab/gitlab.d.ts +34 -1
- package/dist/plus/integrations/providers/gitlab/gitlab.js +118 -4
- package/dist/plus/integrations/providers/gitlab/gitlab.js.map +1 -1
- package/dist/plus/integrations/providers/gitlab/models.d.ts +70 -5
- package/dist/plus/integrations/providers/gitlab/models.js +106 -13
- package/dist/plus/integrations/providers/gitlab/models.js.map +1 -1
- package/dist/plus/integrations/providers/gitlab.d.ts +31 -2
- package/dist/plus/integrations/providers/gitlab.js +48 -8
- package/dist/plus/integrations/providers/gitlab.js.map +1 -1
- package/dist/plus/integrations/providers/jira-server.d.ts +3 -2
- package/dist/plus/integrations/providers/jira-server.js +18 -9
- package/dist/plus/integrations/providers/jira-server.js.map +1 -1
- package/dist/plus/integrations/providers/jira.d.ts +26 -2
- package/dist/plus/integrations/providers/jira.js +120 -9
- package/dist/plus/integrations/providers/jira.js.map +1 -1
- package/dist/plus/integrations/providers/jiraIssueByKey.d.ts +79 -0
- package/dist/plus/integrations/providers/jiraIssueByKey.js +58 -7
- package/dist/plus/integrations/providers/jiraIssueByKey.js.map +1 -1
- package/dist/plus/integrations/providers/linear.d.ts +19 -1
- package/dist/plus/integrations/providers/linear.js +105 -7
- package/dist/plus/integrations/providers/linear.js.map +1 -1
- package/dist/plus/integrations/providers/linearIssuesEtag.d.ts +42 -0
- package/dist/plus/integrations/providers/linearIssuesEtag.js +94 -0
- package/dist/plus/integrations/providers/linearIssuesEtag.js.map +1 -0
- package/dist/plus/integrations/providers/models.d.ts +70 -8
- package/dist/plus/integrations/providers/models.js +59 -21
- package/dist/plus/integrations/providers/models.js.map +1 -1
- package/dist/plus/integrations/providers/providerErrors.js +8 -1
- package/dist/plus/integrations/providers/providerErrors.js.map +1 -1
- package/dist/plus/integrations/providers/providersApi.d.ts +70 -4
- package/dist/plus/integrations/providers/providersApi.js +148 -4
- package/dist/plus/integrations/providers/providersApi.js.map +1 -1
- package/dist/plus/integrations/providers/pullRequestReviews.d.ts +13 -0
- package/dist/plus/integrations/providers/pullRequestReviews.js +30 -6
- package/dist/plus/integrations/providers/pullRequestReviews.js.map +1 -1
- package/dist/plus/integrations/providers/trello.js +11 -7
- package/dist/plus/integrations/providers/trello.js.map +1 -1
- package/dist/plus/integrations/providers/utils/providerPaging.d.ts +11 -0
- package/dist/plus/integrations/providers/utils/providerPaging.js +47 -1
- package/dist/plus/integrations/providers/utils/providerPaging.js.map +1 -1
- package/dist/plus/integrations/providers/utils.d.ts +1 -1
- package/dist/plus/integrations/reads/batchEtags.d.ts +69 -0
- package/dist/plus/integrations/reads/batchEtags.js +114 -0
- package/dist/plus/integrations/reads/batchEtags.js.map +1 -0
- package/dist/plus/integrations/reads/counts.js +2 -2
- package/dist/plus/integrations/reads/counts.js.map +1 -1
- package/dist/plus/integrations/reads/currentAccount.js +2 -2
- package/dist/plus/integrations/reads/currentAccount.js.map +1 -1
- package/dist/plus/integrations/reads/cursors.d.ts +8 -0
- package/dist/plus/integrations/reads/cursors.js +5 -3
- package/dist/plus/integrations/reads/cursors.js.map +1 -1
- package/dist/plus/integrations/reads/drains.d.ts +13 -4
- package/dist/plus/integrations/reads/drains.js +29 -5
- package/dist/plus/integrations/reads/drains.js.map +1 -1
- package/dist/plus/integrations/reads/etag.d.ts +26 -0
- package/dist/plus/integrations/reads/etag.js +108 -0
- package/dist/plus/integrations/reads/etag.js.map +1 -0
- package/dist/plus/integrations/reads/filters.d.ts +8 -0
- package/dist/plus/integrations/reads/filters.js +2 -1
- package/dist/plus/integrations/reads/filters.js.map +1 -1
- package/dist/plus/integrations/reads/hierarchy.js +3 -3
- package/dist/plus/integrations/reads/hierarchy.js.map +1 -1
- package/dist/plus/integrations/reads/issueBatch.d.ts +47 -16
- package/dist/plus/integrations/reads/issueBatch.js +55 -87
- package/dist/plus/integrations/reads/issueBatch.js.map +1 -1
- package/dist/plus/integrations/reads/issueTracker.d.ts +10 -2
- package/dist/plus/integrations/reads/issueTracker.js +23 -6
- package/dist/plus/integrations/reads/issueTracker.js.map +1 -1
- package/dist/plus/integrations/reads/issues.d.ts +1 -1
- package/dist/plus/integrations/reads/issues.js +4 -4
- package/dist/plus/integrations/reads/issues.js.map +1 -1
- package/dist/plus/integrations/reads/pullRequestBatch.d.ts +44 -6
- package/dist/plus/integrations/reads/pullRequestBatch.js +31 -34
- package/dist/plus/integrations/reads/pullRequestBatch.js.map +1 -1
- package/dist/plus/integrations/reads/pullRequestBranches.d.ts +5 -2
- package/dist/plus/integrations/reads/pullRequestBranches.js +4 -3
- package/dist/plus/integrations/reads/pullRequestBranches.js.map +1 -1
- package/dist/plus/integrations/reads/pullRequests.js +8 -4
- package/dist/plus/integrations/reads/pullRequests.js.map +1 -1
- package/dist/plus/integrations/reads/sweeps.js +8 -4
- package/dist/plus/integrations/reads/sweeps.js.map +1 -1
- package/dist/plus/integrations/reads/warnings.d.ts +23 -8
- package/dist/plus/integrations/reads/warnings.js +43 -19
- package/dist/plus/integrations/reads/warnings.js.map +1 -1
- package/dist/plus/integrations/results.d.ts +12 -4
- package/dist/plus/integrations/results.js +2 -0
- package/dist/plus/integrations/results.js.map +1 -1
- package/docs/integrations.md +389 -23
- package/docs/kepler-read-api-parity.md +16 -2
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pullRequest.utils.js","names":[],"sources":["../../../../git/src/utils/pullRequest.utils.ts"],"sourcesContent":["import type {\n\tPullRequest,\n\tPullRequestComparisonRefs,\n\tPullRequestRefs,\n\tPullRequestRepositoryIdentityDescriptor,\n\tPullRequestShape,\n\tPullRequestSortField,\n\tPullRequestSorting,\n\tPullRequestStackInfo,\n} from '../models/pullRequest.js';\nimport { shortenRevision } from './revision.utils.js';\n\n/** How many pull requests a merge action affects — unstacked is always 1; a stacked merge lands either\n * just this layer and everything below it (`position`), or the whole stack (`wholeStack`). The one\n * source every merge-confirmation and merge-action label counts from, so they can't drift apart.\n * Takes only the two fields it needs (not the full {@link PullRequestStackInfo}) since callers on the\n * webview side carry narrower serialized stack shapes. */\nexport function getStackedMergeCount(\n\tstack: Pick<PullRequestStackInfo, 'position' | 'size'> | undefined,\n\toptions?: { wholeStack?: boolean },\n): number {\n\tif (stack == null) return 1;\n\treturn options?.wholeStack ? stack.size : stack.position;\n}\n\n/**\n * How each sort field is read off a {@link PullRequestShape}, for the filtered PR search, which MERGES its\n * relationship × state facets in the facade and so has to order the union itself instead of trusting the\n * per-facet server order. Only the fields the shape carries appear — the same rule as `getIssueComparator`, and\n * the reason {@link PullRequestSortField} is just these two.\n */\nconst pullRequestSortValues: Partial<\n\tRecord<PullRequestSortField, (pr: PullRequestShape) => number | Date | string | undefined>\n> = {\n\tcreated: pr => pr.createdDate,\n\tupdated: pr => pr.updatedDate,\n};\n\n/**\n * A comparator for one sort key over normalized pull requests, or `undefined` when the field isn't derivable\n * from a {@link PullRequestShape} — the signal that the key is only honorable on a SINGLE-origin read where the\n * provider already ordered the page. Missing values sort LAST in both directions (partitioned before any\n * arithmetic so two missing values compare equal, exactly as `getIssueComparator` does).\n *\n * Note it orders whatever it is handed. Sorting a page already capped at the result ceiling does not make it the\n * top N.\n */\nexport function getPullRequestComparator(\n\tsort: PullRequestSorting,\n): ((a: PullRequestShape, b: PullRequestShape) => number) | undefined {\n\tconst [field, direction] = sort.split(':') as [PullRequestSortField, 'asc' | 'desc'];\n\tconst getValue = pullRequestSortValues[field];\n\tif (getValue == null) return undefined;\n\n\treturn (a, b) => {\n\t\tconst left = toComparable(getValue(a));\n\t\tconst right = toComparable(getValue(b));\n\t\tif (left == null || right == null) {\n\t\t\tif (left == null && right == null) return 0;\n\n\t\t\treturn left == null ? 1 : -1;\n\t\t}\n\n\t\tconst ordered = left < right ? -1 : left > right ? 1 : 0;\n\t\treturn direction === 'asc' ? ordered : -ordered;\n\t};\n}\n\nfunction toComparable(value: number | Date | string | undefined): number | string | undefined {\n\treturn value instanceof Date ? value.getTime() : value;\n}\n\nexport interface PullRequestUrlIdentity<TProvider extends string = string> {\n\tprovider?: TProvider;\n\n\townerAndRepo?: string;\n\tprNumber: string;\n}\n\nexport function getComparisonRefsForPullRequest(repoPath: string, prRefs: PullRequestRefs): PullRequestComparisonRefs {\n\tconst refs: PullRequestComparisonRefs = {\n\t\trepoPath: repoPath,\n\t\tbase: { ref: prRefs.base.sha, label: `${prRefs.base.branch} (${shortenRevision(prRefs.base.sha)})` },\n\t\thead: { ref: prRefs.head.sha, label: prRefs.head.branch },\n\t};\n\treturn refs;\n}\n\nexport function getPullRequestIdentityFromMaybeUrl(search: string): PullRequestUrlIdentity | undefined {\n\tlet prNumber: string | undefined = undefined;\n\n\tlet match = search.match(/(?:\\/)(\\d+)/); // any number starting with \"/\"\n\tif (match != null) {\n\t\tprNumber = match[1];\n\t}\n\n\tif (prNumber == null) {\n\t\tmatch = search.match(/^#?(\\d+)$/); // just a number or with a leading \"#\"\n\t\tif (match != null) {\n\t\t\tprNumber = match[1];\n\t\t}\n\t}\n\n\treturn prNumber == null ? undefined : { ownerAndRepo: undefined, prNumber: prNumber, provider: undefined };\n}\n\n/** A pull request's display number from its url, or `undefined` for a url naming no pull request. Anchors\n * on the provider's pull request path segment (GitHub `pull`, Bitbucket `pull-requests`, GitLab\n * `merge_requests`, Azure `pullrequest`) so a digit-leading owner (`github.com/1Password/x/pull/123`)\n * can't win. */\nexport function getPullRequestNumberFromUrl(url: string): string | undefined {\n\t// No loose fallback: `getPullRequestIdentityFromMaybeUrl` scans for any `/<digits>`, which reads a bare\n\t// repository url like `github.com/1Password/sdk` as pull request #1. Callers that hold a real pull\n\t// request fall back to its id instead, and the one that asks whether a pasted url names a pull request\n\t// needs \"no\" for an answer.\n\treturn url.match(/(?:pull|pull-requests|merge_requests|pullrequest)\\/(\\d+)(?:\\b|\\/|$)/)?.[1];\n}\n\nexport function getRepositoryIdentityForPullRequest(\n\tpr: PullRequest,\n\theadRepo: boolean = true,\n): PullRequestRepositoryIdentityDescriptor {\n\tif (headRepo) {\n\t\treturn {\n\t\t\tremote: {\n\t\t\t\turl: pr.refs?.head?.url,\n\t\t\t\tdomain: pr.provider.domain,\n\t\t\t},\n\t\t\tname: `${pr.refs?.head?.owner ?? pr.repository.owner}/${pr.refs?.head?.repo ?? pr.repository.repo}`,\n\t\t\tprovider: {\n\t\t\t\tid: pr.provider.id,\n\t\t\t\tdomain: pr.provider.domain,\n\t\t\t\trepoDomain: pr.refs?.head?.owner ?? pr.repository.owner,\n\t\t\t\trepoName: pr.refs?.head?.repo ?? pr.repository.repo,\n\t\t\t},\n\t\t};\n\t}\n\n\treturn {\n\t\tremote: {\n\t\t\turl: pr.refs?.base?.url ?? pr.url,\n\t\t\tdomain: pr.provider.domain,\n\t\t},\n\t\tname: `${pr.refs?.base?.owner ?? pr.repository.owner}/${pr.refs?.base?.repo ?? pr.repository.repo}`,\n\t\tprovider: {\n\t\t\tid: pr.provider.id,\n\t\t\tdomain: pr.provider.domain,\n\t\t\trepoDomain: pr.refs?.base?.owner ?? pr.repository.owner,\n\t\t\trepoName: pr.refs?.base?.repo ?? pr.repository.repo,\n\t\t\trepoOwnerDomain: pr.refs?.base?.owner ?? pr.repository.owner,\n\t\t},\n\t};\n}\n\nexport function isMaybeNonSpecificPullRequestSearchUrl(search: string): boolean {\n\treturn getPullRequestIdentityFromMaybeUrl(search) != null;\n}\n\nexport function serializePullRequest(value: PullRequest): PullRequestShape {\n\tconst serialized: PullRequestShape = {\n\t\ttype: value.type,\n\t\tprovider: {\n\t\t\tid: value.provider.id,\n\t\t\tname: value.provider.name,\n\t\t\tdomain: value.provider.domain,\n\t\t\ticon: value.provider.icon,\n\t\t},\n\t\tid: value.id,\n\t\tnodeId: value.nodeId,\n\t\tnumber: value.number,\n\t\ttitle: value.title,\n\t\tbody: value.body,\n\t\turl: value.url,\n\t\tcreatedDate: value.createdDate,\n\t\tupdatedDate: value.updatedDate,\n\t\tclosedDate: value.closedDate,\n\t\tclosed: value.closed,\n\t\tauthor: {\n\t\t\tid: value.author.id,\n\t\t\tname: value.author.name,\n\t\t\tusername: value.author.username,\n\t\t\tavatarUrl: value.author.avatarUrl,\n\t\t\turl: value.author.url,\n\t\t},\n\t\tstate: value.state,\n\t\tmergedDate: value.mergedDate,\n\t\tmergeableState: value.mergeableState,\n\t\trefs: value.refs\n\t\t\t? {\n\t\t\t\t\thead: {\n\t\t\t\t\t\texists: value.refs.head.exists,\n\t\t\t\t\t\towner: value.refs.head.owner,\n\t\t\t\t\t\trepo: value.refs.head.repo,\n\t\t\t\t\t\tsha: value.refs.head.sha,\n\t\t\t\t\t\tbranch: value.refs.head.branch,\n\t\t\t\t\t\turl: value.refs.head.url,\n\t\t\t\t\t\tcloneHttps: value.refs.head.cloneHttps,\n\t\t\t\t\t\tcloneSsh: value.refs.head.cloneSsh,\n\t\t\t\t\t\tisFork: value.refs.head.isFork,\n\t\t\t\t\t},\n\t\t\t\t\tbase: {\n\t\t\t\t\t\texists: value.refs.base.exists,\n\t\t\t\t\t\towner: value.refs.base.owner,\n\t\t\t\t\t\trepo: value.refs.base.repo,\n\t\t\t\t\t\tsha: value.refs.base.sha,\n\t\t\t\t\t\tbranch: value.refs.base.branch,\n\t\t\t\t\t\turl: value.refs.base.url,\n\t\t\t\t\t\tcloneHttps: value.refs.base.cloneHttps,\n\t\t\t\t\t\tcloneSsh: value.refs.base.cloneSsh,\n\t\t\t\t\t\tisFork: value.refs.base.isFork,\n\t\t\t\t\t},\n\t\t\t\t\tisCrossRepository: value.refs.isCrossRepository,\n\t\t\t\t}\n\t\t\t: undefined,\n\t\tisDraft: value.isDraft,\n\t\tadditions: value.additions,\n\t\tdeletions: value.deletions,\n\t\tcommentsCount: value.commentsCount,\n\t\tthumbsUpCount: value.thumbsUpCount,\n\t\treviewDecision: value.reviewDecision,\n\t\treviewRequests: value.reviewRequests,\n\t\tlatestReviews: value.latestReviews,\n\t\tassignees: value.assignees,\n\t\tauthoredByMe: value.authoredByMe,\n\t\tproject: value.project\n\t\t\t? {\n\t\t\t\t\tid: value.project.id,\n\t\t\t\t\tname: value.project.name,\n\t\t\t\t\tresourceId: value.project.resourceId,\n\t\t\t\t\tresourceName: value.project.resourceName,\n\t\t\t\t}\n\t\t\t: undefined,\n\t\tstack: value.stack\n\t\t\t? {\n\t\t\t\t\tid: value.stack.id,\n\t\t\t\t\tnumber: value.stack.number,\n\t\t\t\t\tsize: value.stack.size,\n\t\t\t\t\tposition: value.stack.position,\n\t\t\t\t\tbaseRef: value.stack.baseRef,\n\t\t\t\t}\n\t\t\t: undefined,\n\t};\n\treturn serialized;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pullRequest.utils.js","names":[],"sources":["../../../../git/src/utils/pullRequest.utils.ts"],"sourcesContent":["import type {\n\tPullRequest,\n\tPullRequestComparisonRefs,\n\tPullRequestRefs,\n\tPullRequestRepositoryIdentityDescriptor,\n\tPullRequestShape,\n\tPullRequestSortField,\n\tPullRequestSorting,\n\tPullRequestStackInfo,\n} from '../models/pullRequest.js';\nimport { shortenRevision } from './revision.utils.js';\n\n/** How many pull requests a merge action affects — unstacked is always 1; a stacked merge lands either\n * just this layer and everything below it (`position`), or the whole stack (`wholeStack`). The one\n * source every merge-confirmation and merge-action label counts from, so they can't drift apart.\n * Takes only the two fields it needs (not the full {@link PullRequestStackInfo}) since callers on the\n * webview side carry narrower serialized stack shapes. */\nexport function getStackedMergeCount(\n\tstack: Pick<PullRequestStackInfo, 'position' | 'size'> | undefined,\n\toptions?: { wholeStack?: boolean },\n): number {\n\tif (stack == null) return 1;\n\treturn options?.wholeStack ? stack.size : stack.position;\n}\n\n/**\n * How each sort field is read off a {@link PullRequestShape}, for the filtered PR search, which MERGES its\n * relationship × state facets in the facade and so has to order the union itself instead of trusting the\n * per-facet server order. Only the fields the shape carries appear — the same rule as `getIssueComparator`, and\n * the reason {@link PullRequestSortField} is just these two.\n */\nconst pullRequestSortValues: Partial<\n\tRecord<PullRequestSortField, (pr: PullRequestShape) => number | Date | string | undefined>\n> = {\n\tcreated: pr => pr.createdDate,\n\tupdated: pr => pr.updatedDate,\n};\n\n/**\n * A comparator for one sort key over normalized pull requests, or `undefined` when the field isn't derivable\n * from a {@link PullRequestShape} — the signal that the key is only honorable on a SINGLE-origin read where the\n * provider already ordered the page. Missing values sort LAST in both directions (partitioned before any\n * arithmetic so two missing values compare equal, exactly as `getIssueComparator` does).\n *\n * Note it orders whatever it is handed. Sorting a page already capped at the result ceiling does not make it the\n * top N.\n */\nexport function getPullRequestComparator(\n\tsort: PullRequestSorting,\n): ((a: PullRequestShape, b: PullRequestShape) => number) | undefined {\n\tconst [field, direction] = sort.split(':') as [PullRequestSortField, 'asc' | 'desc'];\n\tconst getValue = pullRequestSortValues[field];\n\tif (getValue == null) return undefined;\n\n\treturn (a, b) => {\n\t\tconst left = toComparable(getValue(a));\n\t\tconst right = toComparable(getValue(b));\n\t\tif (left == null || right == null) {\n\t\t\tif (left == null && right == null) return 0;\n\n\t\t\treturn left == null ? 1 : -1;\n\t\t}\n\n\t\tconst ordered = left < right ? -1 : left > right ? 1 : 0;\n\t\treturn direction === 'asc' ? ordered : -ordered;\n\t};\n}\n\nfunction toComparable(value: number | Date | string | undefined): number | string | undefined {\n\treturn value instanceof Date ? value.getTime() : value;\n}\n\nexport interface PullRequestUrlIdentity<TProvider extends string = string> {\n\tprovider?: TProvider;\n\n\townerAndRepo?: string;\n\tprNumber: string;\n}\n\nexport function getComparisonRefsForPullRequest(repoPath: string, prRefs: PullRequestRefs): PullRequestComparisonRefs {\n\tconst refs: PullRequestComparisonRefs = {\n\t\trepoPath: repoPath,\n\t\tbase: { ref: prRefs.base.sha, label: `${prRefs.base.branch} (${shortenRevision(prRefs.base.sha)})` },\n\t\thead: { ref: prRefs.head.sha, label: prRefs.head.branch },\n\t};\n\treturn refs;\n}\n\nexport function getPullRequestIdentityFromMaybeUrl(search: string): PullRequestUrlIdentity | undefined {\n\tlet prNumber: string | undefined = undefined;\n\n\tlet match = search.match(/(?:\\/)(\\d+)/); // any number starting with \"/\"\n\tif (match != null) {\n\t\tprNumber = match[1];\n\t}\n\n\tif (prNumber == null) {\n\t\tmatch = search.match(/^#?(\\d+)$/); // just a number or with a leading \"#\"\n\t\tif (match != null) {\n\t\t\tprNumber = match[1];\n\t\t}\n\t}\n\n\treturn prNumber == null ? undefined : { ownerAndRepo: undefined, prNumber: prNumber, provider: undefined };\n}\n\n/** A pull request's display number from its url, or `undefined` for a url naming no pull request. Anchors\n * on the provider's pull request path segment (GitHub `pull`, Bitbucket `pull-requests`, GitLab\n * `merge_requests`, Azure `pullrequest`) so a digit-leading owner (`github.com/1Password/x/pull/123`)\n * can't win. */\nexport function getPullRequestNumberFromUrl(url: string): string | undefined {\n\t// No loose fallback: `getPullRequestIdentityFromMaybeUrl` scans for any `/<digits>`, which reads a bare\n\t// repository url like `github.com/1Password/sdk` as pull request #1. Callers that hold a real pull\n\t// request fall back to its id instead, and the one that asks whether a pasted url names a pull request\n\t// needs \"no\" for an answer.\n\treturn url.match(/(?:pull|pull-requests|merge_requests|pullrequest)\\/(\\d+)(?:\\b|\\/|$)/)?.[1];\n}\n\nexport function getRepositoryIdentityForPullRequest(\n\tpr: PullRequest,\n\theadRepo: boolean = true,\n): PullRequestRepositoryIdentityDescriptor {\n\tif (headRepo) {\n\t\treturn {\n\t\t\tremote: {\n\t\t\t\turl: pr.refs?.head?.url,\n\t\t\t\tdomain: pr.provider.domain,\n\t\t\t},\n\t\t\tname: `${pr.refs?.head?.owner ?? pr.repository.owner}/${pr.refs?.head?.repo ?? pr.repository.repo}`,\n\t\t\tprovider: {\n\t\t\t\tid: pr.provider.id,\n\t\t\t\tdomain: pr.provider.domain,\n\t\t\t\trepoDomain: pr.refs?.head?.owner ?? pr.repository.owner,\n\t\t\t\trepoName: pr.refs?.head?.repo ?? pr.repository.repo,\n\t\t\t},\n\t\t};\n\t}\n\n\treturn {\n\t\tremote: {\n\t\t\turl: pr.refs?.base?.url ?? pr.url,\n\t\t\tdomain: pr.provider.domain,\n\t\t},\n\t\tname: `${pr.refs?.base?.owner ?? pr.repository.owner}/${pr.refs?.base?.repo ?? pr.repository.repo}`,\n\t\tprovider: {\n\t\t\tid: pr.provider.id,\n\t\t\tdomain: pr.provider.domain,\n\t\t\trepoDomain: pr.refs?.base?.owner ?? pr.repository.owner,\n\t\t\trepoName: pr.refs?.base?.repo ?? pr.repository.repo,\n\t\t\trepoOwnerDomain: pr.refs?.base?.owner ?? pr.repository.owner,\n\t\t},\n\t};\n}\n\nexport function isMaybeNonSpecificPullRequestSearchUrl(search: string): boolean {\n\treturn getPullRequestIdentityFromMaybeUrl(search) != null;\n}\n\n/**\n * Deliberately leaves `projection` out: this copy drops `filesChanged`, `repository` and the class-only check rollup,\n * commit count and `viewerCanUpdate`, so a tag would have field presence report as fetched what the copy no longer has.\n */\nexport function serializePullRequest(value: PullRequest): PullRequestShape {\n\tconst serialized: PullRequestShape = {\n\t\ttype: value.type,\n\t\tprovider: {\n\t\t\tid: value.provider.id,\n\t\t\tname: value.provider.name,\n\t\t\tdomain: value.provider.domain,\n\t\t\ticon: value.provider.icon,\n\t\t},\n\t\tid: value.id,\n\t\tnodeId: value.nodeId,\n\t\tnumber: value.number,\n\t\ttitle: value.title,\n\t\tbody: value.body,\n\t\turl: value.url,\n\t\tcreatedDate: value.createdDate,\n\t\tupdatedDate: value.updatedDate,\n\t\tclosedDate: value.closedDate,\n\t\tclosed: value.closed,\n\t\tauthor: {\n\t\t\tid: value.author.id,\n\t\t\tname: value.author.name,\n\t\t\tusername: value.author.username,\n\t\t\tavatarUrl: value.author.avatarUrl,\n\t\t\turl: value.author.url,\n\t\t},\n\t\tstate: value.state,\n\t\tmergedDate: value.mergedDate,\n\t\tmergeableState: value.mergeableState,\n\t\trefs: value.refs\n\t\t\t? {\n\t\t\t\t\thead: {\n\t\t\t\t\t\texists: value.refs.head.exists,\n\t\t\t\t\t\towner: value.refs.head.owner,\n\t\t\t\t\t\trepo: value.refs.head.repo,\n\t\t\t\t\t\tsha: value.refs.head.sha,\n\t\t\t\t\t\tbranch: value.refs.head.branch,\n\t\t\t\t\t\turl: value.refs.head.url,\n\t\t\t\t\t\tcloneHttps: value.refs.head.cloneHttps,\n\t\t\t\t\t\tcloneSsh: value.refs.head.cloneSsh,\n\t\t\t\t\t\tisFork: value.refs.head.isFork,\n\t\t\t\t\t},\n\t\t\t\t\tbase: {\n\t\t\t\t\t\texists: value.refs.base.exists,\n\t\t\t\t\t\towner: value.refs.base.owner,\n\t\t\t\t\t\trepo: value.refs.base.repo,\n\t\t\t\t\t\tsha: value.refs.base.sha,\n\t\t\t\t\t\tbranch: value.refs.base.branch,\n\t\t\t\t\t\turl: value.refs.base.url,\n\t\t\t\t\t\tcloneHttps: value.refs.base.cloneHttps,\n\t\t\t\t\t\tcloneSsh: value.refs.base.cloneSsh,\n\t\t\t\t\t\tisFork: value.refs.base.isFork,\n\t\t\t\t\t},\n\t\t\t\t\tisCrossRepository: value.refs.isCrossRepository,\n\t\t\t\t}\n\t\t\t: undefined,\n\t\tisDraft: value.isDraft,\n\t\tadditions: value.additions,\n\t\tdeletions: value.deletions,\n\t\tcommentsCount: value.commentsCount,\n\t\tthumbsUpCount: value.thumbsUpCount,\n\t\treviewDecision: value.reviewDecision,\n\t\treviewRequests: value.reviewRequests,\n\t\tlatestReviews: value.latestReviews,\n\t\tassignees: value.assignees,\n\t\tauthoredByMe: value.authoredByMe,\n\t\tviewer: value.viewer != null ? { id: value.viewer.id, username: value.viewer.username } : undefined,\n\t\tproject: value.project\n\t\t\t? {\n\t\t\t\t\tid: value.project.id,\n\t\t\t\t\tname: value.project.name,\n\t\t\t\t\tresourceId: value.project.resourceId,\n\t\t\t\t\tresourceName: value.project.resourceName,\n\t\t\t\t}\n\t\t\t: undefined,\n\t\tstack: value.stack\n\t\t\t? {\n\t\t\t\t\tid: value.stack.id,\n\t\t\t\t\tnumber: value.stack.number,\n\t\t\t\t\tsize: value.stack.size,\n\t\t\t\t\tposition: value.stack.position,\n\t\t\t\t\tbaseRef: value.stack.baseRef,\n\t\t\t\t}\n\t\t\t: undefined,\n\t};\n\treturn serialized;\n}\n"],"mappings":"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"}
|
|
@@ -11,7 +11,7 @@ import { Account, UnidentifiedAuthor } from "../../../git/models/author.js";
|
|
|
11
11
|
import { DefaultBranch } from "../../../git/models/defaultBranch.js";
|
|
12
12
|
import { RepositoryMetadata } from "../../../git/models/repositoryMetadata.js";
|
|
13
13
|
import { GitHubApiConfig } from "./config.js";
|
|
14
|
-
import { GitHubBlame, GitHubBranch, GitHubCommit, GitHubCommitRef, GitHubContributor, GitHubPagedResult, GitHubPullRequestState, GitHubSshSigningKey, GitHubTag } from "../models.js";
|
|
14
|
+
import { GitHubBlame, GitHubBranch, GitHubCommit, GitHubCommitRef, GitHubContributor, GitHubIssueEtagInclude, GitHubIssueEtagNode, GitHubPagedResult, GitHubPullRequestEtagInclude, GitHubPullRequestEtagNode, GitHubPullRequestState, GitHubSshSigningKey, GitHubTag } from "../models.js";
|
|
15
15
|
import { GitHubTokenInfo } from "./token.js";
|
|
16
16
|
import { Endpoints } from "@octokit/types";
|
|
17
17
|
//#region ../plus/git-github/src/api/github.d.ts
|
|
@@ -270,6 +270,7 @@ export declare class GitHubApi {
|
|
|
270
270
|
cursor?: string;
|
|
271
271
|
hasMore: boolean;
|
|
272
272
|
truncated: boolean;
|
|
273
|
+
totalCount?: number;
|
|
273
274
|
}>;
|
|
274
275
|
/**
|
|
275
276
|
* The whole list rather than a page: this read has no cursor to hand back (its `IntegrationResult<T[]>` return
|
|
@@ -447,6 +448,37 @@ export declare class GitHubApi {
|
|
|
447
448
|
baseUrl?: string;
|
|
448
449
|
avatarSize?: number;
|
|
449
450
|
}, cancellation?: AbortSignal): Promise<PromiseSettledResult<PullRequest | undefined>[]>;
|
|
451
|
+
/**
|
|
452
|
+
* The cheap check behind the batch reads' etags: {@link getPullRequestsBatch}'s aliased document, slot rules and
|
|
453
|
+
* failure handling, selecting only a pull request's change state ({@link gqlPullRequestEtagFragment}) — plus
|
|
454
|
+
* the selection of each of `etagIncludes` ({@link gqlPullRequestEtagIncludeFragments}). Returns the raw nodes:
|
|
455
|
+
* the caller maps them through the same conversions a full row takes, so both reads' etags agree.
|
|
456
|
+
*
|
|
457
|
+
* Declares no `$avatarSize`: nothing here selects an avatar, and GitHub rejects a document that declares a
|
|
458
|
+
* variable it never uses.
|
|
459
|
+
*/
|
|
460
|
+
getPullRequestsEtagFieldsBatch(provider: Provider, token: GitHubTokenInfo, coordinates: readonly {
|
|
461
|
+
owner: string;
|
|
462
|
+
repo: string;
|
|
463
|
+
number: number;
|
|
464
|
+
}[], options?: {
|
|
465
|
+
baseUrl?: string;
|
|
466
|
+
etagIncludes?: readonly GitHubPullRequestEtagInclude[];
|
|
467
|
+
}, cancellation?: AbortSignal): Promise<PromiseSettledResult<GitHubPullRequestEtagNode | undefined>[]>;
|
|
468
|
+
/**
|
|
469
|
+
* The issue twin of {@link getPullRequestsEtagFieldsBatch}: {@link getIssuesBatch}'s aliased document, slot
|
|
470
|
+
* rules and failure handling, selecting only an issue's change state ({@link gqlIssueEtagFragment}) — plus the
|
|
471
|
+
* selection of each of `etagIncludes` ({@link gqlIssueEtagIncludeFragments}). Returns the raw nodes, and declares
|
|
472
|
+
* no `$avatarSize`, for the same reasons.
|
|
473
|
+
*/
|
|
474
|
+
getIssuesEtagFieldsBatch(provider: Provider, token: GitHubTokenInfo, coordinates: readonly {
|
|
475
|
+
owner: string;
|
|
476
|
+
repo: string;
|
|
477
|
+
number: number;
|
|
478
|
+
}[], options?: {
|
|
479
|
+
baseUrl?: string;
|
|
480
|
+
etagIncludes?: readonly GitHubIssueEtagInclude[];
|
|
481
|
+
}, cancellation?: AbortSignal): Promise<PromiseSettledResult<GitHubIssueEtagNode | undefined>[]>;
|
|
450
482
|
/**
|
|
451
483
|
* Finds, for several branches in one request, every pull request whose head is that branch — in any state,
|
|
452
484
|
* most recently updated first, up to `limit` per branch. Each target names the BASE repository the pull
|
|
@@ -460,9 +492,12 @@ export declare class GitHubApi {
|
|
|
460
492
|
*
|
|
461
493
|
* `headRefName` matches every fork's branch of that name too, so rows are kept only when their head
|
|
462
494
|
* repository is the base repository itself (`headOwner` omitted) or a fork owned by `headOwner` — otherwise
|
|
463
|
-
* a `main` in the base repository would claim every fork's `main`.
|
|
464
|
-
* `
|
|
465
|
-
*
|
|
495
|
+
* a `main` in the base repository would claim every fork's `main`. The fork is matched by
|
|
496
|
+
* `headRepositoryOwner`, which GitHub keeps after the fork is deleted, so a deleted fork's pull request still
|
|
497
|
+
* matches its old owner. That filter runs after the server's `limit`, so `truncated` is set whenever the server
|
|
498
|
+
* matched more rows than it returned, since any of the unfetched ones might have passed it;
|
|
499
|
+
* {@link getPullRequestNumbersForBranch} settles such a target, though it can't see a deleted fork's pull
|
|
500
|
+
* request, so its caller keeps the rows matched here as well.
|
|
466
501
|
*
|
|
467
502
|
* Returns POSITIONALLY, with the same per-alias rules as {@link getPullRequestsBatch}: a missing base
|
|
468
503
|
* repository (NOT_FOUND on a null repository) is a PROVEN "none" — an empty list — while any other error on
|
|
@@ -481,6 +516,31 @@ export declare class GitHubApi {
|
|
|
481
516
|
pullRequests: PullRequest[];
|
|
482
517
|
truncated: boolean;
|
|
483
518
|
}>[]>;
|
|
519
|
+
/**
|
|
520
|
+
* The numbers of the pull requests into `owner/repo` whose head is `branch` in the repository `headOwner` owns
|
|
521
|
+
* — the base repository's owner when omitted — in any state, most recently updated first, at most `limit`.
|
|
522
|
+
* Only the numbers, so a caller resolves the rows through the same read as its by-number lookups.
|
|
523
|
+
*
|
|
524
|
+
* REST, because its `head` filter matches the head repository's OWNER and the branch on the server, before the
|
|
525
|
+
* page is cut, where GraphQL's `headRefName` matches the name across every fork: this settles a target
|
|
526
|
+
* {@link getPullRequestsForBranches} reported `truncated` only because other forks share its branch name.
|
|
527
|
+
* Keyed on the ref NAME like that read, so a merged pull request whose branch was deleted still matches; one
|
|
528
|
+
* whose fork was deleted has no head repository and matches nothing, so this can't prove such a pull request
|
|
529
|
+
* absent.
|
|
530
|
+
*
|
|
531
|
+
* Strict: an empty list means GitHub answered, and any failure throws, a 404 included — the caller has already
|
|
532
|
+
* read the base repository, so a missing one here proves nothing. A server error or timeout is left to the
|
|
533
|
+
* calling batch to report once (see `reportRequestFailure`), and an authentication failure prompts nothing,
|
|
534
|
+
* since one target's refusal isn't the credential's.
|
|
535
|
+
*/
|
|
536
|
+
getPullRequestNumbersForBranch(provider: Provider, token: GitHubTokenInfo, owner: string, repo: string, branch: string, options: {
|
|
537
|
+
baseUrl?: string;
|
|
538
|
+
headOwner?: string;
|
|
539
|
+
limit: number;
|
|
540
|
+
}, cancellation?: AbortSignal): Promise<{
|
|
541
|
+
numbers: number[];
|
|
542
|
+
truncated: boolean;
|
|
543
|
+
}>;
|
|
484
544
|
/**
|
|
485
545
|
* The PR twin of {@link countIssues}: counts pull requests for several scopes in ONE request via aliased
|
|
486
546
|
* `search` fields selecting only `issueCount` with `first: 0`. Same positional/undefined contract as the issue
|
|
@@ -303,6 +303,59 @@ repository {
|
|
|
303
303
|
}
|
|
304
304
|
`;
|
|
305
305
|
/**
|
|
306
|
+
* The change state a pull request's etag reads (see {@link GitHubPullRequestEtagNode}). Every selection is copied
|
|
307
|
+
* from {@link gqlPullRequestFragment} — same arguments, same nesting — so the cheap read sees exactly the values
|
|
308
|
+
* the full read maps; only a requested reviewer drops its avatar and URL, since its nullness is all the etag reads.
|
|
309
|
+
* `merged` is not needed: `state` already reads `MERGED`.
|
|
310
|
+
*/
|
|
311
|
+
const gqlPullRequestEtagFragment = `
|
|
312
|
+
id
|
|
313
|
+
number
|
|
314
|
+
state
|
|
315
|
+
isDraft
|
|
316
|
+
updatedAt
|
|
317
|
+
headRefOid
|
|
318
|
+
`;
|
|
319
|
+
/**
|
|
320
|
+
* The selection each {@link GitHubPullRequestEtagInclude} adds to {@link gqlPullRequestEtagFragment}, copied from
|
|
321
|
+
* {@link gqlPullRequestFragment} like it.
|
|
322
|
+
*/
|
|
323
|
+
const gqlPullRequestEtagIncludeFragments = {
|
|
324
|
+
mergeable: `
|
|
325
|
+
mergeable
|
|
326
|
+
`,
|
|
327
|
+
reviewDecision: `
|
|
328
|
+
reviewDecision
|
|
329
|
+
`,
|
|
330
|
+
checks: `
|
|
331
|
+
commits(last: 1) {
|
|
332
|
+
nodes {
|
|
333
|
+
commit {
|
|
334
|
+
statusCheckRollup {
|
|
335
|
+
state
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
`
|
|
341
|
+
};
|
|
342
|
+
/** The change state an issue's etag reads (see {@link GitHubIssueEtagNode}). */
|
|
343
|
+
const gqlIssueEtagFragment = `
|
|
344
|
+
id
|
|
345
|
+
number
|
|
346
|
+
state
|
|
347
|
+
updatedAt
|
|
348
|
+
`;
|
|
349
|
+
/**
|
|
350
|
+
* The selection each {@link GitHubIssueEtagInclude} adds to {@link gqlIssueEtagFragment}, copied from
|
|
351
|
+
* {@link gqIssueFragment} like it.
|
|
352
|
+
*/
|
|
353
|
+
const gqlIssueEtagIncludeFragments = { reactions: `
|
|
354
|
+
reactions(content: THUMBS_UP) {
|
|
355
|
+
totalCount
|
|
356
|
+
}
|
|
357
|
+
` };
|
|
358
|
+
/**
|
|
306
359
|
* What an alias's own errors say about its slot in an {@link AliasedGraphqlResult}: `'absent'` only when its node
|
|
307
360
|
* is null and every error on it is NOT_FOUND; a rejection when a node arrived with an error, or on any other error
|
|
308
361
|
* (even a NOT_FOUND nested under the node), since neither is trustworthy; `undefined` when the alias has no errors.
|
|
@@ -571,7 +624,7 @@ var GitHubApi = class {
|
|
|
571
624
|
number
|
|
572
625
|
}, scope);
|
|
573
626
|
if (rsp?.repository?.issue == null) return void 0;
|
|
574
|
-
return fromGitHubIssue(rsp.repository.issue, provider);
|
|
627
|
+
return fromGitHubIssue(rsp.repository.issue, provider, issueProjection("point", options));
|
|
575
628
|
} catch (ex) {
|
|
576
629
|
if (ex instanceof RequestNotFoundError) return void 0;
|
|
577
630
|
throw this.handleException(ex, provider, scope);
|
|
@@ -600,7 +653,7 @@ var GitHubApi = class {
|
|
|
600
653
|
number
|
|
601
654
|
}, scope);
|
|
602
655
|
if (rsp?.repository?.pullRequest == null) return void 0;
|
|
603
|
-
return fromGitHubPullRequestLite(rsp.repository.pullRequest, provider);
|
|
656
|
+
return fromGitHubPullRequestLite(rsp.repository.pullRequest, provider, "point");
|
|
604
657
|
} catch (ex) {
|
|
605
658
|
if (ex instanceof RequestNotFoundError) return void 0;
|
|
606
659
|
throw this.handleException(ex, provider, scope);
|
|
@@ -637,7 +690,7 @@ var GitHubApi = class {
|
|
|
637
690
|
}, scope))?.repository?.ref?.associatedPullRequests?.nodes?.filter((pr) => pr != null && (!pr.repository.isFork || pr.repository.owner.login === owner));
|
|
638
691
|
if (prs == null || prs.length === 0) return void 0;
|
|
639
692
|
if (prs.length > 1) prs.sort((a, b) => (a.repository.owner.login === owner ? -1 : 1) - (b.repository.owner.login === owner ? -1 : 1) || (a.state === "OPEN" ? -1 : 1) - (b.state === "OPEN" ? -1 : 1) || new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());
|
|
640
|
-
return fromGitHubPullRequestLite(prs[0], provider);
|
|
693
|
+
return fromGitHubPullRequestLite(prs[0], provider, "point");
|
|
641
694
|
} catch (ex) {
|
|
642
695
|
if (ex instanceof RequestNotFoundError) return void 0;
|
|
643
696
|
throw this.handleException(ex, provider, scope);
|
|
@@ -674,7 +727,7 @@ var GitHubApi = class {
|
|
|
674
727
|
}, scope, cancellation))?.repository?.object?.associatedPullRequests?.nodes?.filter((pr) => pr != null && (!pr.repository.isFork || pr.repository.owner.login === owner));
|
|
675
728
|
if (prs == null || prs.length === 0) return void 0;
|
|
676
729
|
if (prs.length > 1) prs.sort((a, b) => (a.repository.owner.login === owner ? -1 : 1) - (b.repository.owner.login === owner ? -1 : 1) || (a.state === "MERGED" ? -1 : 1) - (b.state === "MERGED" ? -1 : 1) || new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());
|
|
677
|
-
return fromGitHubPullRequestLite(prs[0], provider);
|
|
730
|
+
return fromGitHubPullRequestLite(prs[0], provider, "point");
|
|
678
731
|
} catch (ex) {
|
|
679
732
|
if (ex instanceof RequestNotFoundError) return void 0;
|
|
680
733
|
throw this.handleException(ex, provider, scope);
|
|
@@ -2040,10 +2093,11 @@ var GitHubApi = class {
|
|
|
2040
2093
|
truncated: false
|
|
2041
2094
|
};
|
|
2042
2095
|
return {
|
|
2043
|
-
values: rsp.search.nodes.map((pr) => options?.summary ? fromGitHubPullRequestLite(pr, provider) : fromGitHubPullRequest(pr, provider)),
|
|
2096
|
+
values: rsp.search.nodes.map((pr) => options?.summary ? fromGitHubPullRequestLite(pr, provider, "search-summary") : fromGitHubPullRequest(pr, provider, "search")),
|
|
2044
2097
|
cursor: rsp.search.pageInfo.endCursor ?? void 0,
|
|
2045
2098
|
hasMore: rsp.search.pageInfo.hasNextPage,
|
|
2046
|
-
truncated: rsp.search.issueCount > 1e3 && !rsp.search.pageInfo.hasNextPage
|
|
2099
|
+
truncated: rsp.search.issueCount > 1e3 && !rsp.search.pageInfo.hasNextPage,
|
|
2100
|
+
totalCount: rsp.search.issueCount
|
|
2047
2101
|
};
|
|
2048
2102
|
} catch (ex) {
|
|
2049
2103
|
throw this.handleException(ex, provider, scope, options?.silent);
|
|
@@ -2124,7 +2178,8 @@ var GitHubApi = class {
|
|
|
2124
2178
|
cursor: options?.cursor,
|
|
2125
2179
|
pageSize: options?.pageSize,
|
|
2126
2180
|
sort: options?.sort,
|
|
2127
|
-
legacySort: unsortedCursorSort
|
|
2181
|
+
legacySort: unsortedCursorSort,
|
|
2182
|
+
projection: "account"
|
|
2128
2183
|
}, cancellation);
|
|
2129
2184
|
}
|
|
2130
2185
|
/**
|
|
@@ -2176,7 +2231,8 @@ var GitHubApi = class {
|
|
|
2176
2231
|
cursor: options?.cursor,
|
|
2177
2232
|
pageSize: options?.pageSize,
|
|
2178
2233
|
sort,
|
|
2179
|
-
legacySort: defaultIssueSort
|
|
2234
|
+
legacySort: defaultIssueSort,
|
|
2235
|
+
projection: "search"
|
|
2180
2236
|
}, cancellation);
|
|
2181
2237
|
}
|
|
2182
2238
|
/**
|
|
@@ -2295,7 +2351,7 @@ var GitHubApi = class {
|
|
|
2295
2351
|
try {
|
|
2296
2352
|
return {
|
|
2297
2353
|
status: "fulfilled",
|
|
2298
|
-
value: fromGitHubIssue(node, provider)
|
|
2354
|
+
value: fromGitHubIssue(node, provider, issueProjection("batch", options))
|
|
2299
2355
|
};
|
|
2300
2356
|
} catch (ex) {
|
|
2301
2357
|
scope?.warn(`failed to map issue; ${c.owner}/${c.repo}#${c.number}, ex=${ex}`);
|
|
@@ -2383,6 +2439,103 @@ var GitHubApi = class {
|
|
|
2383
2439
|
}
|
|
2384
2440
|
}
|
|
2385
2441
|
/**
|
|
2442
|
+
* The cheap check behind the batch reads' etags: {@link getPullRequestsBatch}'s aliased document, slot rules and
|
|
2443
|
+
* failure handling, selecting only a pull request's change state ({@link gqlPullRequestEtagFragment}) — plus
|
|
2444
|
+
* the selection of each of `etagIncludes` ({@link gqlPullRequestEtagIncludeFragments}). Returns the raw nodes:
|
|
2445
|
+
* the caller maps them through the same conversions a full row takes, so both reads' etags agree.
|
|
2446
|
+
*
|
|
2447
|
+
* Declares no `$avatarSize`: nothing here selects an avatar, and GitHub rejects a document that declares a
|
|
2448
|
+
* variable it never uses.
|
|
2449
|
+
*/
|
|
2450
|
+
async getPullRequestsEtagFieldsBatch(provider, token, coordinates, options, cancellation) {
|
|
2451
|
+
const scope = getScopedLogger();
|
|
2452
|
+
if (coordinates.length === 0) return [];
|
|
2453
|
+
const includeFragments = Array.from(new Set(options?.etagIncludes), (include) => gqlPullRequestEtagIncludeFragments[include]);
|
|
2454
|
+
const query = `query getPullRequestsEtagFieldsBatch(
|
|
2455
|
+
${coordinates.map((_, i) => `$o${i}: String!\n\t\t\t\t$n${i}: String!\n\t\t\t\t$k${i}: Int!`).join("\n ")}
|
|
2456
|
+
) {
|
|
2457
|
+
${coordinates.map((_, i) => `p${i}: repository(owner: $o${i}, name: $n${i}) {
|
|
2458
|
+
pullRequest(number: $k${i}) {
|
|
2459
|
+
${gqlPullRequestEtagFragment}
|
|
2460
|
+
${includeFragments.join("")}
|
|
2461
|
+
}
|
|
2462
|
+
}`).join("\n ")}
|
|
2463
|
+
}`;
|
|
2464
|
+
const variables = { baseUrl: options?.baseUrl };
|
|
2465
|
+
coordinates.forEach((c, i) => {
|
|
2466
|
+
variables[`o${i}`] = c.owner;
|
|
2467
|
+
variables[`n${i}`] = c.repo;
|
|
2468
|
+
variables[`k${i}`] = c.number;
|
|
2469
|
+
});
|
|
2470
|
+
try {
|
|
2471
|
+
const rsp = await this.graphql(provider, token, query, variables, scope, cancellation, "aliased");
|
|
2472
|
+
if (rsp?.data == null) throw new Error("GitHub returned no data for the pull request etag batch");
|
|
2473
|
+
return coordinates.map((_, i) => {
|
|
2474
|
+
const alias = `p${i}`;
|
|
2475
|
+
const node = rsp.data[alias]?.pullRequest;
|
|
2476
|
+
const verdict = getAliasErrorVerdict(rsp.errors, alias, node);
|
|
2477
|
+
if (verdict === "absent") return {
|
|
2478
|
+
status: "fulfilled",
|
|
2479
|
+
value: void 0
|
|
2480
|
+
};
|
|
2481
|
+
if (verdict != null) return verdict;
|
|
2482
|
+
return {
|
|
2483
|
+
status: "fulfilled",
|
|
2484
|
+
value: node ?? void 0
|
|
2485
|
+
};
|
|
2486
|
+
});
|
|
2487
|
+
} catch (ex) {
|
|
2488
|
+
throw this.handleException(ex, provider, scope);
|
|
2489
|
+
}
|
|
2490
|
+
}
|
|
2491
|
+
/**
|
|
2492
|
+
* The issue twin of {@link getPullRequestsEtagFieldsBatch}: {@link getIssuesBatch}'s aliased document, slot
|
|
2493
|
+
* rules and failure handling, selecting only an issue's change state ({@link gqlIssueEtagFragment}) — plus the
|
|
2494
|
+
* selection of each of `etagIncludes` ({@link gqlIssueEtagIncludeFragments}). Returns the raw nodes, and declares
|
|
2495
|
+
* no `$avatarSize`, for the same reasons.
|
|
2496
|
+
*/
|
|
2497
|
+
async getIssuesEtagFieldsBatch(provider, token, coordinates, options, cancellation) {
|
|
2498
|
+
const scope = getScopedLogger();
|
|
2499
|
+
if (coordinates.length === 0) return [];
|
|
2500
|
+
const includeFragments = Array.from(new Set(options?.etagIncludes), (include) => gqlIssueEtagIncludeFragments[include]);
|
|
2501
|
+
const query = `query getIssuesEtagFieldsBatch(
|
|
2502
|
+
${coordinates.map((_, i) => `$o${i}: String!\n\t\t\t\t$n${i}: String!\n\t\t\t\t$k${i}: Int!`).join("\n ")}
|
|
2503
|
+
) {
|
|
2504
|
+
${coordinates.map((_, i) => `i${i}: repository(owner: $o${i}, name: $n${i}) {
|
|
2505
|
+
issue(number: $k${i}) {
|
|
2506
|
+
${gqlIssueEtagFragment}
|
|
2507
|
+
${includeFragments.join("")}
|
|
2508
|
+
}
|
|
2509
|
+
}`).join("\n ")}
|
|
2510
|
+
}`;
|
|
2511
|
+
const variables = { baseUrl: options?.baseUrl };
|
|
2512
|
+
coordinates.forEach((c, i) => {
|
|
2513
|
+
variables[`o${i}`] = c.owner;
|
|
2514
|
+
variables[`n${i}`] = c.repo;
|
|
2515
|
+
variables[`k${i}`] = c.number;
|
|
2516
|
+
});
|
|
2517
|
+
try {
|
|
2518
|
+
const rsp = await this.graphql(provider, token, query, variables, scope, cancellation, "aliased");
|
|
2519
|
+
if (rsp?.data == null) throw new Error("GitHub returned no data for the issue etag batch");
|
|
2520
|
+
return coordinates.map((_, i) => {
|
|
2521
|
+
const alias = `i${i}`;
|
|
2522
|
+
const node = rsp.data[alias]?.issue;
|
|
2523
|
+
const verdict = getAliasErrorVerdict(rsp.errors, alias, node);
|
|
2524
|
+
if (verdict === "absent") return {
|
|
2525
|
+
status: "fulfilled",
|
|
2526
|
+
value: void 0
|
|
2527
|
+
};
|
|
2528
|
+
if (verdict != null) return verdict;
|
|
2529
|
+
return {
|
|
2530
|
+
status: "fulfilled",
|
|
2531
|
+
value: node ?? void 0
|
|
2532
|
+
};
|
|
2533
|
+
});
|
|
2534
|
+
} catch (ex) {
|
|
2535
|
+
throw this.handleException(ex, provider, scope);
|
|
2536
|
+
}
|
|
2537
|
+
}
|
|
2538
|
+
/**
|
|
2386
2539
|
* Finds, for several branches in one request, every pull request whose head is that branch — in any state,
|
|
2387
2540
|
* most recently updated first, up to `limit` per branch. Each target names the BASE repository the pull
|
|
2388
2541
|
* requests are opened against, the head branch's short name and, for a branch that lives in a fork,
|
|
@@ -2395,9 +2548,12 @@ var GitHubApi = class {
|
|
|
2395
2548
|
*
|
|
2396
2549
|
* `headRefName` matches every fork's branch of that name too, so rows are kept only when their head
|
|
2397
2550
|
* repository is the base repository itself (`headOwner` omitted) or a fork owned by `headOwner` — otherwise
|
|
2398
|
-
* a `main` in the base repository would claim every fork's `main`.
|
|
2399
|
-
* `
|
|
2400
|
-
*
|
|
2551
|
+
* a `main` in the base repository would claim every fork's `main`. The fork is matched by
|
|
2552
|
+
* `headRepositoryOwner`, which GitHub keeps after the fork is deleted, so a deleted fork's pull request still
|
|
2553
|
+
* matches its old owner. That filter runs after the server's `limit`, so `truncated` is set whenever the server
|
|
2554
|
+
* matched more rows than it returned, since any of the unfetched ones might have passed it;
|
|
2555
|
+
* {@link getPullRequestNumbersForBranch} settles such a target, though it can't see a deleted fork's pull
|
|
2556
|
+
* request, so its caller keeps the rows matched here as well.
|
|
2401
2557
|
*
|
|
2402
2558
|
* Returns POSITIONALLY, with the same per-alias rules as {@link getPullRequestsBatch}: a missing base
|
|
2403
2559
|
* repository (NOT_FOUND on a null repository) is a PROVEN "none" — an empty list — while any other error on
|
|
@@ -2478,6 +2634,45 @@ var GitHubApi = class {
|
|
|
2478
2634
|
}
|
|
2479
2635
|
}
|
|
2480
2636
|
/**
|
|
2637
|
+
* The numbers of the pull requests into `owner/repo` whose head is `branch` in the repository `headOwner` owns
|
|
2638
|
+
* — the base repository's owner when omitted — in any state, most recently updated first, at most `limit`.
|
|
2639
|
+
* Only the numbers, so a caller resolves the rows through the same read as its by-number lookups.
|
|
2640
|
+
*
|
|
2641
|
+
* REST, because its `head` filter matches the head repository's OWNER and the branch on the server, before the
|
|
2642
|
+
* page is cut, where GraphQL's `headRefName` matches the name across every fork: this settles a target
|
|
2643
|
+
* {@link getPullRequestsForBranches} reported `truncated` only because other forks share its branch name.
|
|
2644
|
+
* Keyed on the ref NAME like that read, so a merged pull request whose branch was deleted still matches; one
|
|
2645
|
+
* whose fork was deleted has no head repository and matches nothing, so this can't prove such a pull request
|
|
2646
|
+
* absent.
|
|
2647
|
+
*
|
|
2648
|
+
* Strict: an empty list means GitHub answered, and any failure throws, a 404 included — the caller has already
|
|
2649
|
+
* read the base repository, so a missing one here proves nothing. A server error or timeout is left to the
|
|
2650
|
+
* calling batch to report once (see `reportRequestFailure`), and an authentication failure prompts nothing,
|
|
2651
|
+
* since one target's refusal isn't the credential's.
|
|
2652
|
+
*/
|
|
2653
|
+
async getPullRequestNumbersForBranch(provider, token, owner, repo, branch, options, cancellation) {
|
|
2654
|
+
const scope = getScopedLogger();
|
|
2655
|
+
try {
|
|
2656
|
+
const rsp = await this.request(provider, token, "GET /repos/{owner}/{repo}/pulls", {
|
|
2657
|
+
owner,
|
|
2658
|
+
repo,
|
|
2659
|
+
head: `${options.headOwner ?? owner}:${branch}`,
|
|
2660
|
+
state: "all",
|
|
2661
|
+
sort: "updated",
|
|
2662
|
+
direction: "desc",
|
|
2663
|
+
per_page: options.limit + 1,
|
|
2664
|
+
baseUrl: options.baseUrl
|
|
2665
|
+
}, scope, cancellation, true);
|
|
2666
|
+
if (rsp?.data == null) throw new Error("GitHub returned no data for the pull requests by head");
|
|
2667
|
+
return {
|
|
2668
|
+
numbers: rsp.data.slice(0, options.limit).map((pr) => pr.number),
|
|
2669
|
+
truncated: rsp.data.length > options.limit
|
|
2670
|
+
};
|
|
2671
|
+
} catch (ex) {
|
|
2672
|
+
throw this.handleException(ex, provider, scope, true);
|
|
2673
|
+
}
|
|
2674
|
+
}
|
|
2675
|
+
/**
|
|
2481
2676
|
* The PR twin of {@link countIssues}: counts pull requests for several scopes in ONE request via aliased
|
|
2482
2677
|
* `search` fields selecting only `issueCount` with `first: 0`. Same positional/undefined contract as the issue
|
|
2483
2678
|
* count.
|
|
@@ -2623,7 +2818,7 @@ var GitHubApi = class {
|
|
|
2623
2818
|
for (const node of rsp[s.alias]?.nodes ?? []) {
|
|
2624
2819
|
if (node?.id == null) continue;
|
|
2625
2820
|
try {
|
|
2626
|
-
const issue = fromGitHubIssue(node, provider);
|
|
2821
|
+
const issue = fromGitHubIssue(node, provider, issueProjection(options.projection, options));
|
|
2627
2822
|
if (seen?.has(issue.url) !== true) mapped.push(issue);
|
|
2628
2823
|
} catch (ex) {
|
|
2629
2824
|
scope?.warn(`skipped unmappable issue; id=${node.id}, url=${node.url}, ex=${ex}`);
|
|
@@ -2798,7 +2993,7 @@ var GitHubApi = class {
|
|
|
2798
2993
|
for (const facet of activeFacets) for (const node of rsp[facet.alias]?.nodes ?? []) {
|
|
2799
2994
|
if (node?.id == null) continue;
|
|
2800
2995
|
try {
|
|
2801
|
-
pullRequests.push(options?.summary ? fromGitHubPullRequestLite(node, provider) : fromGitHubPullRequest(node, provider));
|
|
2996
|
+
pullRequests.push(options?.summary ? fromGitHubPullRequestLite(node, provider, "search-summary") : fromGitHubPullRequest(node, provider, "search"));
|
|
2802
2997
|
} catch (ex) {
|
|
2803
2998
|
scope?.warn(`skipped unmappable pull request; id=${node.id}, url=${node.url}, ex=${ex}`);
|
|
2804
2999
|
}
|
|
@@ -2900,7 +3095,7 @@ var GitHubApi = class {
|
|
|
2900
3095
|
const rsp = await this.graphql(provider, token, query, variables, scope, cancellation);
|
|
2901
3096
|
if (rsp == null) return [];
|
|
2902
3097
|
const results = [];
|
|
2903
|
-
for (const { alias } of stateSearches) for (const node of rsp[alias]?.nodes ?? []) results.push(fromGitHubPullRequest(node, provider));
|
|
3098
|
+
for (const { alias } of stateSearches) for (const node of rsp[alias]?.nodes ?? []) results.push(fromGitHubPullRequest(node, provider, "text-search"));
|
|
2904
3099
|
return [...uniqueBy(filterPullRequestsBySearchState(results, include), (pr) => pr.url, (original, _current) => original)].slice(0, pageSize);
|
|
2905
3100
|
} catch (ex) {
|
|
2906
3101
|
throw this.handleException(ex, provider, scope);
|
|
@@ -3255,10 +3450,25 @@ __decorate([trace({ args: (provider, token) => ({
|
|
|
3255
3450
|
provider: provider.name,
|
|
3256
3451
|
token: `<token:${token.microHash}>`
|
|
3257
3452
|
}) })], GitHubApi.prototype, "getPullRequestsBatch", null);
|
|
3453
|
+
__decorate([trace({ args: (provider, token) => ({
|
|
3454
|
+
provider: provider.name,
|
|
3455
|
+
token: `<token:${token.microHash}>`
|
|
3456
|
+
}) })], GitHubApi.prototype, "getPullRequestsEtagFieldsBatch", null);
|
|
3457
|
+
__decorate([trace({ args: (provider, token) => ({
|
|
3458
|
+
provider: provider.name,
|
|
3459
|
+
token: `<token:${token.microHash}>`
|
|
3460
|
+
}) })], GitHubApi.prototype, "getIssuesEtagFieldsBatch", null);
|
|
3258
3461
|
__decorate([trace({ args: (provider, token) => ({
|
|
3259
3462
|
provider: provider.name,
|
|
3260
3463
|
token: `<token:${token.microHash}>`
|
|
3261
3464
|
}) })], GitHubApi.prototype, "getPullRequestsForBranches", null);
|
|
3465
|
+
__decorate([trace({ args: (provider, token, owner, repo, branch) => ({
|
|
3466
|
+
provider: provider.name,
|
|
3467
|
+
token: `<token:${token.microHash}>`,
|
|
3468
|
+
owner,
|
|
3469
|
+
repo,
|
|
3470
|
+
branch
|
|
3471
|
+
}) })], GitHubApi.prototype, "getPullRequestNumbersForBranch", null);
|
|
3262
3472
|
__decorate([trace({ args: (provider, token) => ({
|
|
3263
3473
|
provider: provider.name,
|
|
3264
3474
|
token: `<token:${token.microHash}>`
|
|
@@ -3291,6 +3501,13 @@ __decorate([trace({ args: (provider, token, nodeId, expectedSourceSha) => ({
|
|
|
3291
3501
|
nodeId,
|
|
3292
3502
|
expectedSourceSha
|
|
3293
3503
|
}) })], GitHubApi.prototype, "mergePullRequest", null);
|
|
3504
|
+
/**
|
|
3505
|
+
* Every issue read's presence table assumes the body was selected, so a read without `includeBody` is left
|
|
3506
|
+
* untagged (unknown) rather than claiming a description it never fetched.
|
|
3507
|
+
*/
|
|
3508
|
+
function issueProjection(projection, options) {
|
|
3509
|
+
return options?.includeBody ? projection : void 0;
|
|
3510
|
+
}
|
|
3294
3511
|
function isGitHubDotCom(options) {
|
|
3295
3512
|
return options?.baseUrl == null || options.baseUrl === "https://api.github.com";
|
|
3296
3513
|
}
|