@gitkraken/core-gitlens 0.7.0 → 0.7.2
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 +28 -2
- package/dist/git/remotes/azure-devops.js +3 -3
- package/dist/git/remotes/azure-devops.js.map +1 -1
- package/dist/plus/integrations/authentication/configuredIntegrationService.js +9 -2
- package/dist/plus/integrations/authentication/configuredIntegrationService.js.map +1 -1
- package/dist/plus/integrations/authentication/integrationAuthenticationProvider.js +1 -1
- package/dist/plus/integrations/collectionMetadata.d.ts +48 -3
- package/dist/plus/integrations/collectionMetadata.js +138 -8
- package/dist/plus/integrations/collectionMetadata.js.map +1 -1
- package/dist/plus/integrations/errors.d.ts +3 -1
- package/dist/plus/integrations/errors.js +7 -3
- package/dist/plus/integrations/errors.js.map +1 -1
- package/dist/plus/integrations/index.d.ts +3 -3
- package/dist/plus/integrations/index.js.map +1 -1
- package/dist/plus/integrations/integrationService.d.ts +35 -1
- package/dist/plus/integrations/integrationService.js +90 -43
- package/dist/plus/integrations/integrationService.js.map +1 -1
- package/dist/plus/integrations/lite.js +5 -4
- package/dist/plus/integrations/lite.js.map +1 -1
- package/dist/plus/integrations/manager.d.ts +68 -23
- package/dist/plus/integrations/models/gitHostIntegration.d.ts +31 -15
- package/dist/plus/integrations/models/gitHostIntegration.js +71 -22
- package/dist/plus/integrations/models/gitHostIntegration.js.map +1 -1
- package/dist/plus/integrations/models/integration.d.ts +70 -12
- package/dist/plus/integrations/models/integration.js +56 -1
- package/dist/plus/integrations/models/integration.js.map +1 -1
- package/dist/plus/integrations/models/issueReads.d.ts +17 -0
- package/dist/plus/integrations/models/issuesIntegration.js +2 -0
- package/dist/plus/integrations/models/issuesIntegration.js.map +1 -1
- package/dist/plus/integrations/models/pullRequestReads.d.ts +26 -0
- package/dist/plus/integrations/providers/azure/azure.d.ts +66 -1
- package/dist/plus/integrations/providers/azure/azure.js +192 -12
- package/dist/plus/integrations/providers/azure/azure.js.map +1 -1
- package/dist/plus/integrations/providers/azure/search.d.ts +144 -0
- package/dist/plus/integrations/providers/azure/search.js +250 -0
- package/dist/plus/integrations/providers/azure/search.js.map +1 -0
- package/dist/plus/integrations/providers/azureDevOps.d.ts +73 -36
- package/dist/plus/integrations/providers/azureDevOps.js +191 -122
- package/dist/plus/integrations/providers/azureDevOps.js.map +1 -1
- package/dist/plus/integrations/providers/azureDevOpsServer.d.ts +176 -0
- package/dist/plus/integrations/providers/azureDevOpsServer.js +560 -0
- package/dist/plus/integrations/providers/azureDevOpsServer.js.map +1 -0
- package/dist/plus/integrations/providers/bitbucket-server/discovery.d.ts +12 -0
- package/dist/plus/integrations/providers/bitbucket-server/discovery.js +128 -0
- package/dist/plus/integrations/providers/bitbucket-server/discovery.js.map +1 -0
- package/dist/plus/integrations/providers/bitbucket-server/models.d.ts +10 -1
- package/dist/plus/integrations/providers/bitbucket-server/models.js +3 -2
- package/dist/plus/integrations/providers/bitbucket-server/models.js.map +1 -1
- package/dist/plus/integrations/providers/bitbucket-server/pullRequestSearch.d.ts +58 -0
- package/dist/plus/integrations/providers/bitbucket-server/pullRequestSearch.js +485 -0
- package/dist/plus/integrations/providers/bitbucket-server/pullRequestSearch.js.map +1 -0
- package/dist/plus/integrations/providers/bitbucket-server.d.ts +61 -3
- package/dist/plus/integrations/providers/bitbucket-server.js +114 -20
- package/dist/plus/integrations/providers/bitbucket-server.js.map +1 -1
- package/dist/plus/integrations/providers/bitbucket.d.ts +9 -1
- package/dist/plus/integrations/providers/bitbucket.js +13 -2
- package/dist/plus/integrations/providers/bitbucket.js.map +1 -1
- package/dist/plus/integrations/providers/github.d.ts +6 -6
- package/dist/plus/integrations/providers/github.js +35 -34
- package/dist/plus/integrations/providers/github.js.map +1 -1
- package/dist/plus/integrations/providers/gitlab.d.ts +6 -4
- package/dist/plus/integrations/providers/gitlab.js +32 -28
- package/dist/plus/integrations/providers/gitlab.js.map +1 -1
- package/dist/plus/integrations/providers/issueSorts.d.ts +1 -0
- package/dist/plus/integrations/providers/jira-server.d.ts +9 -0
- package/dist/plus/integrations/providers/jira-server.js +15 -7
- package/dist/plus/integrations/providers/jira-server.js.map +1 -1
- package/dist/plus/integrations/providers/jira.d.ts +9 -0
- package/dist/plus/integrations/providers/jira.js +14 -2
- package/dist/plus/integrations/providers/jira.js.map +1 -1
- package/dist/plus/integrations/providers/linear.js +2 -2
- package/dist/plus/integrations/providers/models.d.ts +10 -1
- package/dist/plus/integrations/providers/models.js +86 -0
- package/dist/plus/integrations/providers/models.js.map +1 -1
- package/dist/plus/integrations/providers/providersApi.d.ts +10 -0
- package/dist/plus/integrations/providers/providersApi.js +18 -3
- package/dist/plus/integrations/providers/providersApi.js.map +1 -1
- package/dist/plus/integrations/providers/utils.d.ts +12 -1
- package/dist/plus/integrations/providers/utils.js +36 -6
- package/dist/plus/integrations/providers/utils.js.map +1 -1
- package/dist/plus/integrations/reads/broaden.js +6 -6
- package/dist/plus/integrations/reads/broaden.js.map +1 -1
- package/dist/plus/integrations/reads/context.d.ts +1 -1
- package/dist/plus/integrations/reads/counts.d.ts +18 -4
- package/dist/plus/integrations/reads/counts.js +66 -15
- package/dist/plus/integrations/reads/counts.js.map +1 -1
- package/dist/plus/integrations/reads/cursors.js +1 -1
- package/dist/plus/integrations/reads/drains.d.ts +2 -1
- package/dist/plus/integrations/reads/drains.js +1 -1
- package/dist/plus/integrations/reads/filters.d.ts +1 -1
- package/dist/plus/integrations/reads/filters.js +17 -12
- package/dist/plus/integrations/reads/filters.js.map +1 -1
- package/dist/plus/integrations/reads/hierarchy.js +2 -2
- package/dist/plus/integrations/reads/hierarchy.js.map +1 -1
- package/dist/plus/integrations/reads/hierarchy.utils.js +1 -1
- package/dist/plus/integrations/reads/issueBatch.js +1 -1
- package/dist/plus/integrations/reads/issueTracker.js +2 -2
- package/dist/plus/integrations/reads/issues.js +2 -2
- package/dist/plus/integrations/reads/paging.js +1 -1
- package/dist/plus/integrations/reads/resolveRepository.d.ts +12 -11
- package/dist/plus/integrations/reads/resolveRepository.js +110 -19
- package/dist/plus/integrations/reads/resolveRepository.js.map +1 -1
- package/dist/plus/integrations/reads/searchIssues.js +4 -2
- package/dist/plus/integrations/reads/searchIssues.js.map +1 -1
- package/dist/plus/integrations/reads/searchPullRequests.js +9 -3
- package/dist/plus/integrations/reads/searchPullRequests.js.map +1 -1
- package/dist/plus/integrations/reads/sweeps.js +1 -1
- package/dist/plus/integrations/reads/trackerIssue.d.ts +9 -5
- package/dist/plus/integrations/reads/trackerIssue.js +15 -9
- package/dist/plus/integrations/reads/trackerIssue.js.map +1 -1
- package/dist/plus/integrations/reads/warnings.d.ts +6 -2
- package/dist/plus/integrations/reads/warnings.js +15 -19
- package/dist/plus/integrations/reads/warnings.js.map +1 -1
- package/dist/plus/integrations/results.d.ts +84 -6
- package/dist/plus/integrations/results.js +9 -2
- package/dist/plus/integrations/results.js.map +1 -1
- package/dist/plus/integrations/utils/domain.utils.d.ts +19 -0
- package/dist/plus/integrations/utils/domain.utils.js +36 -1
- package/dist/plus/integrations/utils/domain.utils.js.map +1 -1
- package/dist/plus/integrations/utils/integration.utils.d.ts +1 -0
- package/dist/plus/integrations/utils/integration.utils.js +12 -1
- package/dist/plus/integrations/utils/integration.utils.js.map +1 -1
- package/docs/integrations.md +263 -74
- package/docs/kepler-read-api-parity.md +19 -6
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github.js","names":[],"sources":["../../../../../plus/integrations/src/providers/github.ts"],"sourcesContent":["import { gitHubPullRequestRelationshipQualifiers } from '@gitlens/git-github/api/pullRequestSearchQuery.js';\nimport type { Account, UnidentifiedAuthor } from '@gitlens/git/models/author.js';\nimport type { DefaultBranch } from '@gitlens/git/models/defaultBranch.js';\nimport type { Issue, IssueSearchCriteria, IssueShape } from '@gitlens/git/models/issue.js';\nimport type { IssueOrPullRequest } from '@gitlens/git/models/issueOrPullRequest.js';\nimport type {\n\tPullRequest,\n\tPullRequestMergeMethod,\n\tPullRequestSearchCriteria,\n\tPullRequestStackInfo,\n\tPullRequestState,\n\tPullRequestStateFilter,\n} from '@gitlens/git/models/pullRequest.js';\nimport type { RepositoryMetadata } from '@gitlens/git/models/repositoryMetadata.js';\nimport type { RepositoryDescriptor } from '@gitlens/git/models/resourceDescriptor.js';\nimport { getGitHubNoReplyAddressParts } from '@gitlens/git/remotes/github.js';\nimport type { PullRequestUrlIdentity } from '@gitlens/git/utils/pullRequest.utils.js';\nimport type { Emitter } from '@gitlens/utils/event.js';\nimport { batch } from '@gitlens/utils/promise.js';\nimport type { IntegrationAuthenticationProviderDescriptor } from '../authentication/integrationAuthenticationProvider.js';\nimport type { IntegrationAuthenticationService } from '../authentication/integrationAuthenticationService.js';\nimport type { ProviderAuthenticationSession } from '../authentication/models.js';\nimport { toTokenWithInfo } from '../authentication/models.js';\nimport { toCollectionScopeFailure } from '../collectionMetadata.js';\nimport { GitCloudHostIntegrationId, GitSelfManagedHostIntegrationId } from '../constants.js';\nimport type { IntegrationServiceContext } from '../context.js';\nimport { IntegrationReadUnavailableError } from '../errors.js';\nimport type { IntegrationConnectionChangeEvent } from '../integrationService.js';\nimport type { SearchMyPullRequestsOptions, SearchPullRequestsOptions } from '../models/gitHostIntegration.js';\nimport { GitHostIntegration } from '../models/gitHostIntegration.js';\nimport type {\n\tProviderIssueSearchPage,\n\tProviderPullRequestSearchPage,\n\tSearchMyIssuesOptions,\n} from '../models/integration.js';\nimport type { GitHubIntegrationIds } from './github/github.utils.js';\nimport { getGitHubPullRequestIdentityFromMaybeUrl } from './github/github.utils.js';\nimport type {\n\tProviderApiPagedResult,\n\tProviderHierarchyResult,\n\tProviderOrganization,\n\tProviderPullRequest,\n\tProviderRepoInput,\n\tProviderRepository,\n} from './models.js';\nimport {\n\tgetProviderPullRequestIdentity,\n\tIssueFilter,\n\tprovidersMetadata,\n\tPullRequestFilter,\n\ttoProviderPullRequest,\n} from './models.js';\nimport type { ProvidersApi } from './providersApi.js';\n\ntype GitHubPullRequestFacetCursor = Record<string, string>;\n\nfunction toPullRequestFacetCursor(value: unknown): GitHubPullRequestFacetCursor {\n\tif (value == null || typeof value !== 'object' || Array.isArray(value)) return {};\n\n\treturn Object.fromEntries(\n\t\tObject.entries(value).filter(\n\t\t\t([key, cursor]) => key.length !== 0 && typeof cursor === 'string' && cursor.length !== 0,\n\t\t),\n\t);\n}\n\nfunction parsePullRequestFacetCursor(cursor: string | undefined): GitHubPullRequestFacetCursor {\n\tif (!cursor) return {};\n\n\ttry {\n\t\tconst parsed = JSON.parse(cursor) as unknown;\n\t\tif (parsed != null && typeof parsed === 'object' && !Array.isArray(parsed) && 'cursors' in parsed) {\n\t\t\tconst wrapped = parsed as { type?: unknown; cursors?: unknown };\n\t\t\tif (wrapped.type === 'cursor') {\n\t\t\t\treturn toPullRequestFacetCursor(wrapped.cursors);\n\t\t\t}\n\t\t}\n\n\t\treturn toPullRequestFacetCursor(parsed);\n\t} catch {\n\t\treturn {};\n\t}\n}\n\nconst metadata = providersMetadata[GitCloudHostIntegrationId.GitHub];\nconst authProvider: IntegrationAuthenticationProviderDescriptor = Object.freeze({\n\tid: metadata.id,\n\tscopes: metadata.scopes,\n});\n\nconst cloudEnterpriseMetadata = providersMetadata[GitSelfManagedHostIntegrationId.CloudGitHubEnterprise];\nconst cloudEnterpriseAuthProvider: IntegrationAuthenticationProviderDescriptor = Object.freeze({\n\tid: cloudEnterpriseMetadata.id,\n\tscopes: cloudEnterpriseMetadata.scopes,\n});\n\nexport type GitHubRepositoryDescriptor = RepositoryDescriptor;\n\n/** How many per-login SSH signing-key lookups to run concurrently, to avoid a request burst that trips rate limiting. */\nconst sshSigningKeyResolveBatchSize = 10;\n\nabstract class GitHubIntegrationBase<ID extends GitHubIntegrationIds> extends GitHostIntegration<\n\tID,\n\tGitHubRepositoryDescriptor\n> {\n\t/**\n\t * Base URL handed to `@gitkraken/provider-apis`, which derives BOTH the REST and the GraphQL endpoint from it\n\t * by appending GitHub Enterprise's paths. Only a GHE instance base belongs here; cloud passes `undefined`,\n\t * the sole value that selects the cloud endpoints (see the cloud subclass).\n\t */\n\tprotected abstract get apiBaseUrl(): string | undefined;\n\n\tprotected override async getProviderAccountForCommit(\n\t\tsession: ProviderAuthenticationSession,\n\t\trepo: GitHubRepositoryDescriptor,\n\t\trev: string,\n\t\toptions?: {\n\t\t\tavatarSize?: number;\n\t\t},\n\t): Promise<Account | UnidentifiedAuthor | undefined> {\n\t\treturn (await this.authenticationService.apis.github)?.getAccountForCommit(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\trepo.owner,\n\t\t\trepo.name,\n\t\t\trev,\n\t\t\t{\n\t\t\t\t...options,\n\t\t\t\tbaseUrl: this.apiBaseUrl,\n\t\t\t},\n\t\t);\n\t}\n\n\tprotected override async getProviderAccountForEmail(\n\t\tsession: ProviderAuthenticationSession,\n\t\trepo: GitHubRepositoryDescriptor,\n\t\temail: string,\n\t\toptions?: {\n\t\t\tavatarSize?: number;\n\t\t},\n\t): Promise<Account | undefined> {\n\t\treturn (await this.authenticationService.apis.github)?.getAccountForEmail(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\trepo.owner,\n\t\t\trepo.name,\n\t\t\temail,\n\t\t\t{\n\t\t\t\t...options,\n\t\t\t\tbaseUrl: this.apiBaseUrl,\n\t\t\t},\n\t\t);\n\t}\n\n\tprotected override async getProviderSshSigningKeysForEmails(\n\t\tsession: ProviderAuthenticationSession,\n\t\trepo: GitHubRepositoryDescriptor,\n\t\temails: string[],\n\t): Promise<Map<string, string[]>> {\n\t\tconst result = new Map<string, string[]>();\n\n\t\tconst api = await this.authenticationService.apis.github;\n\t\tif (api == null) return result;\n\n\t\tconst token = toTokenWithInfo(this.id, session);\n\n\t\t// Resolve each email to a login: GitHub noreply addresses encode it locally; the rest are resolved in a single\n\t\t// batched GraphQL request rather than one round-trip per email.\n\t\tconst loginByEmail = new Map<string, string>();\n\t\tconst toResolve: string[] = [];\n\t\tfor (const email of emails) {\n\t\t\tconst login = getGitHubNoReplyAddressParts(email)?.login;\n\t\t\tif (login != null) {\n\t\t\t\tloginByEmail.set(email.toLowerCase(), login);\n\t\t\t} else {\n\t\t\t\ttoResolve.push(email);\n\t\t\t}\n\t\t}\n\n\t\tif (toResolve.length) {\n\t\t\tconst resolved = await api.getAccountsForEmails(this, token, toResolve, { baseUrl: this.apiBaseUrl });\n\t\t\tfor (const [emailLower, login] of resolved) {\n\t\t\t\tloginByEmail.set(emailLower, login);\n\t\t\t}\n\t\t}\n\n\t\t// Fetch signing keys once per distinct login (REST has no batch endpoint), in bounded batches rather than firing\n\t\t// all lookups at once, to avoid a request burst that could trip secondary rate limiting. Then map keys to each email.\n\t\tconst keysByLogin = new Map<string, string[]>();\n\t\tawait batch([...new Set(loginByEmail.values())], sshSigningKeyResolveBatchSize, async login => {\n\t\t\tconst keys = await api.getUserSshSigningKeys(this, token, login, { baseUrl: this.apiBaseUrl });\n\t\t\tkeysByLogin.set(\n\t\t\t\tlogin,\n\t\t\t\tkeys.map(k => k.key),\n\t\t\t);\n\t\t});\n\n\t\tfor (const [emailLower, login] of loginByEmail) {\n\t\t\tresult.set(emailLower, keysByLogin.get(login) ?? []);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprotected override async getProviderDefaultBranch(\n\t\tsession: ProviderAuthenticationSession,\n\t\trepo: GitHubRepositoryDescriptor,\n\t): Promise<DefaultBranch | undefined> {\n\t\treturn (await this.authenticationService.apis.github)?.getDefaultBranch(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\trepo.owner,\n\t\t\trepo.name,\n\t\t\t{\n\t\t\t\tbaseUrl: this.apiBaseUrl,\n\t\t\t},\n\t\t);\n\t}\n\n\tprotected override async getProviderLinkedIssueOrPullRequest(\n\t\tsession: ProviderAuthenticationSession,\n\t\trepo: GitHubRepositoryDescriptor,\n\t\t{ id }: { id: string; key: string },\n\t): Promise<IssueOrPullRequest | undefined> {\n\t\treturn (await this.authenticationService.apis.github)?.getIssueOrPullRequest(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\trepo.owner,\n\t\t\trepo.name,\n\t\t\tNumber(id),\n\t\t\t{\n\t\t\t\tbaseUrl: this.apiBaseUrl,\n\t\t\t},\n\t\t);\n\t}\n\n\tprotected override async getProviderIssue(\n\t\tsession: ProviderAuthenticationSession,\n\t\trepo: GitHubRepositoryDescriptor,\n\t\tid: string,\n\t): Promise<Issue | undefined> {\n\t\treturn (await this.authenticationService.apis.github)?.getIssue(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\trepo.owner,\n\t\t\trepo.name,\n\t\t\tNumber(id),\n\t\t\t{\n\t\t\t\tbaseUrl: this.apiBaseUrl,\n\t\t\t\tincludeBody: true,\n\t\t\t},\n\t\t);\n\t}\n\n\tprotected override async getProviderPullRequest(\n\t\tsession: ProviderAuthenticationSession,\n\t\trepo: GitHubRepositoryDescriptor,\n\t\tid: string,\n\t): Promise<PullRequest | undefined> {\n\t\treturn (await this.authenticationService.apis.github)?.getPullRequest(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\trepo.owner,\n\t\t\trepo.name,\n\t\t\tparseInt(id, 10),\n\t\t\t{\n\t\t\t\tbaseUrl: this.apiBaseUrl,\n\t\t\t},\n\t\t);\n\t}\n\n\tprotected override async getProviderPullRequestForBranch(\n\t\tsession: ProviderAuthenticationSession,\n\t\trepo: GitHubRepositoryDescriptor,\n\t\tbranch: string,\n\t\toptions?: {\n\t\t\tavatarSize?: number;\n\t\t\tinclude?: PullRequestState[];\n\t\t},\n\t): Promise<PullRequest | undefined> {\n\t\tconst { include, ...opts } = options ?? {};\n\n\t\tconst toGitHubPullRequestState = (await import(/* webpackChunkName: \"integrations\" */ './github/models.js'))\n\t\t\t.toGitHubPullRequestState;\n\t\treturn (await this.authenticationService.apis.github)?.getPullRequestForBranch(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\trepo.owner,\n\t\t\trepo.name,\n\t\t\tbranch,\n\t\t\t{\n\t\t\t\t...opts,\n\t\t\t\tinclude: include?.map(s => toGitHubPullRequestState(s)),\n\t\t\t\tbaseUrl: this.apiBaseUrl,\n\t\t\t},\n\t\t);\n\t}\n\n\tprotected override async getProviderPullRequestForCommit(\n\t\tsession: ProviderAuthenticationSession,\n\t\trepo: GitHubRepositoryDescriptor,\n\t\trev: string,\n\t): Promise<PullRequest | undefined> {\n\t\treturn (await this.authenticationService.apis.github)?.getPullRequestForCommit(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\trepo.owner,\n\t\t\trepo.name,\n\t\t\trev,\n\t\t\t{\n\t\t\t\tbaseUrl: this.apiBaseUrl,\n\t\t\t},\n\t\t);\n\t}\n\n\tprotected override async getProviderRepositoryMetadata(\n\t\tsession: ProviderAuthenticationSession,\n\t\trepo: GitHubRepositoryDescriptor,\n\t\tcancellation?: AbortSignal,\n\t): Promise<RepositoryMetadata | undefined> {\n\t\treturn (await this.authenticationService.apis.github)?.getRepositoryMetadata(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\trepo.owner,\n\t\t\trepo.name,\n\t\t\t{\n\t\t\t\tbaseUrl: this.apiBaseUrl,\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\tprotected override async getProviderOrganizationsForUser(\n\t\tsession: ProviderAuthenticationSession,\n\t): Promise<ProviderHierarchyResult<ProviderOrganization> | undefined> {\n\t\tconst api = await this.getProvidersApi();\n\t\tconst result = await api.getGitHubOrgsForCurrentUser(toTokenWithInfo(this.id, session), {\n\t\t\tbaseUrl: this.apiBaseUrl,\n\t\t});\n\t\treturn {\n\t\t\tvalues: result.values.map(o => ({\n\t\t\t\tid: o.id,\n\t\t\t\tproviderId: this.id,\n\t\t\t\tname: o.username,\n\t\t\t\turl: `https://${this.domain}/${o.username}`,\n\t\t\t})),\n\t\t\t...(result.truncated ? { truncated: true } : {}),\n\t\t\t...(result.metadata != null ? { metadata: result.metadata } : {}),\n\t\t};\n\t}\n\n\tprotected override async getProviderRepositoriesForOrg(\n\t\tsession: ProviderAuthenticationSession,\n\t\torg: string,\n\t\toptions?: { cursor?: string },\n\t): Promise<ProviderHierarchyResult<ProviderRepository> | undefined> {\n\t\tconst api = await this.getProvidersApi();\n\t\treturn api.getReposForOrg(toTokenWithInfo(this.id, session), org, {\n\t\t\tbaseUrl: this.apiBaseUrl,\n\t\t\tcursor: options?.cursor,\n\t\t});\n\t}\n\n\tprotected override async getProviderRepositoriesForUser(\n\t\tsession: ProviderAuthenticationSession,\n\t\toptions?: { cursor?: string },\n\t): Promise<ProviderHierarchyResult<ProviderRepository> | undefined> {\n\t\tconst api = await this.getProvidersApi();\n\t\t// `/user/repos` with the full affiliation set: the user's own repos, collaborations, and org-member\n\t\t// repos — matching gkcli's org-less `provider repos github` walk (not every repo of every org).\n\t\treturn api.getReposForCurrentUser(toTokenWithInfo(this.id, session), {\n\t\t\taffiliations: ['owner', 'collaborator', 'organization_member'],\n\t\t\tbaseUrl: this.apiBaseUrl,\n\t\t\tcursor: options?.cursor,\n\t\t});\n\t}\n\n\tpublic override async getRepoInfo(repo: {\n\t\towner: string;\n\t\tname: string;\n\t\tproject?: string;\n\t\tconnectionId?: string;\n\t}): Promise<ProviderRepository | undefined> {\n\t\tconst api = await this.getProvidersApi();\n\t\t// `connectionId` targets a specific account (multi-account); omitted reads the primary.\n\t\tconst session = await this.resolveReadSession(repo.connectionId, undefined);\n\t\tif (session == null) return undefined;\n\n\t\t// `apiBaseUrl` is undefined for cloud (which is what selects the cloud endpoints) and the GHE instance base\n\t\t// for enterprise (inherited override).\n\t\treturn api.getRepo(toTokenWithInfo(this.id, session), repo.owner, repo.name, repo.project, {\n\t\t\tbaseUrl: this.apiBaseUrl,\n\t\t});\n\t}\n\n\tprotected override async searchProviderMyPullRequests(\n\t\tsession: ProviderAuthenticationSession,\n\t\trepos?: GitHubRepositoryDescriptor[],\n\t\tcancellation?: AbortSignal,\n\t\toptions?: SearchMyPullRequestsOptions,\n\t): Promise<PullRequest[] | undefined> {\n\t\treturn (await this.authenticationService.apis.github)?.searchMyPullRequests(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\t{\n\t\t\t\trepos: repos?.map(r => `${r.owner}/${r.name}`),\n\t\t\t\tbaseUrl: this.apiBaseUrl,\n\t\t\t\tsilent: options?.silent,\n\t\t\t\tstate: options?.state,\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\tprotected override async getProviderMyPullRequestsForUser(\n\t\tsession: ProviderAuthenticationSession,\n\t\toptions?: {\n\t\t\tstate?: PullRequestStateFilter[];\n\t\t\tcursor?: string;\n\t\t\tincludeReviewRequested?: boolean;\n\t\t\tfilters?: PullRequestFilter[];\n\t\t\tsummary?: boolean;\n\t\t},\n\t): Promise<ProviderApiPagedResult<ProviderPullRequest> | undefined> {\n\t\tconst explicitFilters = options?.filters?.length ? [...new Set(options.filters)] : undefined;\n\t\t// Every account-wide read goes through our own facet search — there is deliberately no SDK\n\t\t// `getPullRequestsForUser` fallback. It could express neither a state set, nor exact relationships (its\n\t\t// `involves:` is a different question), nor the full projection, so which reads it could serve depended on\n\t\t// the options, and the two routes disagreed on more than they had to: only this one applies the Launchpad\n\t\t// ignored/included repository and organization qualifiers, so the same read returned different pull\n\t\t// requests depending on options that were supposed to affect only projection or relationship. With no\n\t\t// state and no filters this emits a single facet with no relationship qualifier, which is GitHub's own\n\t\t// `involves:@me` and `is:open` default — the same question the fallback asked, now on one route.\n\t\tconst github = await this.authenticationService.apis.github;\n\t\tif (github == null) return undefined;\n\n\t\tconst requestedStates: PullRequestStateFilter[] =\n\t\t\toptions?.state != null && options.state.length > 0 ? [...new Set(options.state)] : ['open'];\n\t\tconst facets =\n\t\t\texplicitFilters?.length != null\n\t\t\t\t? requestedStates.flatMap(state =>\n\t\t\t\t\t\texplicitFilters.map(filter => ({\n\t\t\t\t\t\t\tkey: `${state}:${filter}`,\n\t\t\t\t\t\t\tstate: state,\n\t\t\t\t\t\t\tsearch: gitHubPullRequestRelationshipQualifiers[filter],\n\t\t\t\t\t\t})),\n\t\t\t\t\t)\n\t\t\t\t: requestedStates.flatMap(state => [\n\t\t\t\t\t\t{ key: state, state: state, search: undefined },\n\t\t\t\t\t\t...(options?.includeReviewRequested === true\n\t\t\t\t\t\t\t? [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tkey: `${state}:${PullRequestFilter.ReviewRequested}`,\n\t\t\t\t\t\t\t\t\t\tstate: state,\n\t\t\t\t\t\t\t\t\t\tsearch: gitHubPullRequestRelationshipQualifiers[\n\t\t\t\t\t\t\t\t\t\t\tPullRequestFilter.ReviewRequested\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t: []),\n\t\t\t\t\t]);\n\t\tconst cursors = parsePullRequestFacetCursor(options?.cursor);\n\t\tconst hasResumableFacetCursor = Object.keys(cursors).length !== 0;\n\t\tconst facetsWithCursor = facets.filter(facet => cursors[facet.key] != null);\n\t\t// The first call has no cursor, so query every requested state. A continuation only happens after a\n\t\t// prior page reported `more:true`, whose bundle carries a cursor for each facet still in flight;\n\t\t// facets absent from the bundle are exhausted, so re-querying them from scratch would refetch the\n\t\t// same PRs (duplicated by the dedup-free sweep) and waste an API call per page. Query only the\n\t\t// states that still have a cursor, but degrade a malformed/empty cursor bundle, or one that doesn't\n\t\t// apply to the current requested states, to the first page rather than returning an empty page.\n\t\tconst facetsToQuery =\n\t\t\toptions?.cursor != null && hasResumableFacetCursor && facetsWithCursor.length !== 0\n\t\t\t\t? facetsWithCursor\n\t\t\t\t: facets;\n\t\tconst results = await Promise.allSettled(\n\t\t\tfacetsToQuery.map(async facet => ({\n\t\t\t\tkey: facet.key,\n\t\t\t\tresult: await github.searchMyPullRequestsPage(this, toTokenWithInfo(this.id, session), {\n\t\t\t\t\tbaseUrl: this.apiBaseUrl,\n\t\t\t\t\tstate: facet.state,\n\t\t\t\t\tcursor: cursors[facet.key],\n\t\t\t\t\tsummary: options?.summary,\n\t\t\t\t\t...(facet.search != null ? { search: facet.search, includeDefaultInvolvement: false } : undefined),\n\t\t\t\t}),\n\t\t\t})),\n\t\t);\n\t\tif (results.every(result => result.status === 'rejected')) {\n\t\t\tconst first = results[0];\n\t\t\tif (first?.status === 'rejected') throw first.reason;\n\t\t}\n\n\t\tconst values = new Map<string, ProviderPullRequest>();\n\t\tconst nextCursors: GitHubPullRequestFacetCursor = {};\n\t\tconst failures = [];\n\t\tlet hasMore = false;\n\t\tlet truncated = false;\n\t\tlet structuralIncompleteness = false;\n\t\tlet unkeyedPullRequest = 0;\n\t\tfor (const outcome of results) {\n\t\t\tif (outcome.status === 'rejected') {\n\t\t\t\tfailures.push(toCollectionScopeFailure({ providerId: this.id }, outcome.reason));\n\t\t\t\ttruncated = true;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst { key, result } = outcome.value;\n\t\t\tfor (const pr of result.values) {\n\t\t\t\tconst mapped = toProviderPullRequest(pr);\n\t\t\t\tconst identity = getProviderPullRequestIdentity(mapped) ?? `unkeyed:${unkeyedPullRequest++}`;\n\t\t\t\tif (!values.has(identity)) {\n\t\t\t\t\tvalues.set(identity, mapped);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (result.hasMore) {\n\t\t\t\tif (result.cursor == null || result.cursor === '{}' || result.cursor === cursors[key]) {\n\t\t\t\t\ttruncated = true;\n\t\t\t\t\tstructuralIncompleteness = true;\n\t\t\t\t} else {\n\t\t\t\t\thasMore = true;\n\t\t\t\t\tnextCursors[key] = result.cursor;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (result.truncated) {\n\t\t\t\ttruncated = true;\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tvalues: [...values.values()],\n\t\t\tpaging: {\n\t\t\t\tmore: hasMore,\n\t\t\t\tcursor: hasMore ? JSON.stringify({ type: 'cursor', cursors: nextCursors }) : '{}',\n\t\t\t\ttruncated: truncated || undefined,\n\t\t\t},\n\t\t\t...(failures.length || structuralIncompleteness\n\t\t\t\t? {\n\t\t\t\t\t\tmetadata: {\n\t\t\t\t\t\t\tcompleteness: 'partial' as const,\n\t\t\t\t\t\t\t...(failures.length ? { failures: failures } : {}),\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t: undefined),\n\t\t};\n\t}\n\n\tprotected override async searchProviderMyIssues(\n\t\tsession: ProviderAuthenticationSession,\n\t\trepos?: GitHubRepositoryDescriptor[],\n\t\tcancellation?: AbortSignal,\n\t): Promise<IssueShape[] | undefined> {\n\t\treturn (await this.searchProviderMyIssuesWithTruncation(session, repos, cancellation))?.values;\n\t}\n\n\t/**\n\t * GitHub's account-wide issue search pages authored/assigned/mentioned independently behind one composite\n\t * cursor. This variant preserves that cursor and the provider's 1,000-result search ceiling signal.\n\t *\n\t * `options.filters` selects which of those three searches run, so a caller can narrow the union to just its\n\t * own slice (e.g. `[Assignee]` ⇒ `assignee:@me`). Omitted keeps GitHub's own definition of \"mine\" (all three).\n\t */\n\tprotected override async searchProviderMyIssuesWithTruncation(\n\t\tsession: ProviderAuthenticationSession,\n\t\trepos?: GitHubRepositoryDescriptor[],\n\t\tcancellation?: AbortSignal,\n\t\toptions?: SearchMyIssuesOptions,\n\t): Promise<{ values: IssueShape[]; truncated: boolean } | undefined> {\n\t\t// `includeAllAssignees` becomes `assignee:*`, which needs a scope to mean anything — with none it matches\n\t\t// millions of issues across all of GitHub rather than \"assigned to anyone in the user's world\". ANY scope\n\t\t// works (one repo, several, or an org), so this refuses only the genuinely unscoped read; the scoped\n\t\t// \"assigned to anyone over these repos\" request is served by `searchIssuesPage`.\n\t\tif ((repos == null || repos.length === 0) && options?.includeAllAssignees) {\n\t\t\tthrow new IntegrationReadUnavailableError(\n\t\t\t\tthis.name,\n\t\t\t\t'`includeAllAssignees` is not supported for account-wide issue reads; scope the read to repositories instead.',\n\t\t\t);\n\t\t}\n\n\t\treturn (await this.authenticationService.apis.github)?.searchMyIssues(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\t{\n\t\t\t\trepos: repos?.map(r => `${r.owner}/${r.name}`),\n\t\t\t\tbaseUrl: this.apiBaseUrl,\n\t\t\t\tincludeBody: true,\n\t\t\t\tincludeAllAssignees: options?.includeAllAssignees,\n\t\t\t\tcursor: options?.cursor,\n\t\t\t\tpageSize: options?.pageSize,\n\t\t\t\tsort: options?.sort,\n\t\t\t\tcategories: options?.filters?.length\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tauthored: options.filters.includes(IssueFilter.Author),\n\t\t\t\t\t\t\tassigned: options.filters.includes(IssueFilter.Assignee),\n\t\t\t\t\t\t\tmentioned: options.filters.includes(IssueFilter.Mention),\n\t\t\t\t\t\t}\n\t\t\t\t\t: undefined,\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\t/**\n\t * Filtered pull-request search over a repository/organization or explicit current-user relationship scope. The\n\t * API client owns criteria sanitizing, facet unioning, ordering, and the composite cursor that carries GitHub's\n\t * result-ceiling signal across pages.\n\t */\n\tprotected override async searchProviderPullRequestsPage(\n\t\tsession: ProviderAuthenticationSession,\n\t\toptions: {\n\t\t\trepos?: ProviderRepoInput[];\n\t\t\torg?: string;\n\t\t\tcriteria?: PullRequestSearchCriteria;\n\t\t\tcursor?: string;\n\t\t\tpageSize?: number;\n\t\t\tsummary?: boolean;\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<ProviderPullRequestSearchPage | undefined> {\n\t\treturn (await this.authenticationService.apis.github)?.searchPullRequestsPage(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\t{\n\t\t\t\trepos: options.repos?.map(r => `${r.namespace}/${r.name}`),\n\t\t\t\torg: options.org,\n\t\t\t\tcriteria: options.criteria,\n\t\t\t\tbaseUrl: this.apiBaseUrl,\n\t\t\t\tcursor: options.cursor,\n\t\t\t\tpageSize: options.pageSize,\n\t\t\t\tsummary: options.summary,\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\t/**\n\t * The filtered issue search: one GraphQL request per page, no forced relationship to the current user, and no\n\t * route through the SDK's repo-scoped read (whose over-limit recovery walk can spend up to 128 requests).\n\t *\n\t * The criteria → qualifier translation and the ordering guarantee live in the API client\n\t * (`GitHubApi.searchIssuesPage`), which is also where user input is sanitized so it can't inject a qualifier.\n\t */\n\tprotected override async searchProviderIssuesPage(\n\t\tsession: ProviderAuthenticationSession,\n\t\toptions: {\n\t\t\trepos?: ProviderRepoInput[];\n\t\t\torg?: string;\n\t\t\tcriteria?: IssueSearchCriteria;\n\t\t\tcursor?: string;\n\t\t\tpageSize?: number;\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<ProviderIssueSearchPage | undefined> {\n\t\treturn (await this.authenticationService.apis.github)?.searchIssuesPage(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\t{\n\t\t\t\t// `namespace` is the owner for GitHub, which is how a `repo:` qualifier names a repository.\n\t\t\t\trepos: options.repos?.map(r => `${r.namespace}/${r.name}`),\n\t\t\t\torg: options.org,\n\t\t\t\tcriteria: options.criteria,\n\t\t\t\tbaseUrl: this.apiBaseUrl,\n\t\t\t\tincludeBody: true,\n\t\t\t\tcursor: options.cursor,\n\t\t\t\tpageSize: options.pageSize,\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\t/**\n\t * Counts several scopes in ONE request. GitHub's `search` reports `issueCount` on a zero-node selection, so a\n\t * count preview costs no issue transfer — measured, 30 aliased counts are a single rate-limit point.\n\t */\n\tprotected override async countProviderIssues(\n\t\tsession: ProviderAuthenticationSession,\n\t\tscopes: readonly { repos?: ProviderRepoInput[]; org?: string; criteria?: IssueSearchCriteria }[],\n\t\tcancellation?: AbortSignal,\n\t): Promise<(number | undefined)[] | undefined> {\n\t\treturn (await this.authenticationService.apis.github)?.countIssues(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\tscopes.map(s => ({\n\t\t\t\trepos: s.repos?.map(r => `${r.namespace}/${r.name}`),\n\t\t\t\torg: s.org,\n\t\t\t\tcriteria: s.criteria,\n\t\t\t})),\n\t\t\t{ baseUrl: this.apiBaseUrl },\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\t/**\n\t * Resolves several issues by `(owner, repo, number)` in ONE request, by aliasing the point read rather than a\n\t * search — see {@link GitHubApi.getIssuesBatch} for why that distinction is the whole design.\n\t */\n\tprotected override async getProviderIssuesBatch(\n\t\tsession: ProviderAuthenticationSession,\n\t\tcoordinates: readonly { owner: string; repo: string; number: number }[],\n\t\tcancellation?: AbortSignal,\n\t): Promise<(IssueShape | undefined)[] | undefined> {\n\t\treturn (await this.authenticationService.apis.github)?.getIssuesBatch(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\tcoordinates,\n\t\t\t{ baseUrl: this.apiBaseUrl, includeBody: true },\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\t/**\n\t * Counts several pull-request scopes in ONE request. Like {@link countProviderIssues}, GitHub's `search`\n\t * reports `issueCount` on a zero-node selection, so a count preview costs no pull-request transfer.\n\t */\n\tprotected override async countProviderPullRequests(\n\t\tsession: ProviderAuthenticationSession,\n\t\tscopes: readonly { repos?: ProviderRepoInput[]; org?: string; criteria?: PullRequestSearchCriteria }[],\n\t\tcancellation?: AbortSignal,\n\t): Promise<(number | undefined)[] | undefined> {\n\t\treturn (await this.authenticationService.apis.github)?.countPullRequests(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\tscopes.map(s => ({\n\t\t\t\trepos: s.repos?.map(r => `${r.namespace}/${r.name}`),\n\t\t\t\torg: s.org,\n\t\t\t\tcriteria: s.criteria,\n\t\t\t})),\n\t\t\t{ baseUrl: this.apiBaseUrl },\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\tprotected override async searchProviderPullRequests(\n\t\tsession: ProviderAuthenticationSession,\n\t\tsearchQuery: string,\n\t\trepos?: GitHubRepositoryDescriptor[],\n\t\tcancellation?: AbortSignal,\n\t\toptions?: SearchPullRequestsOptions,\n\t): Promise<PullRequest[] | undefined> {\n\t\treturn (await this.authenticationService.apis.github)?.searchPullRequests(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\t{\n\t\t\t\tsearch: searchQuery,\n\t\t\t\trepos: repos?.map(r => `${r.owner}/${r.name}`),\n\t\t\t\tbaseUrl: this.apiBaseUrl,\n\t\t\t\t...options,\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\t/**\n\t * Stack membership for every stacked pull request in the repository, keyed by pull request number.\n\t *\n\t * List surfaces get their pull requests from the shared providers API, whose type carries no stack\n\t * membership, so the `stack`/`stackEntry` fields selected on the native per-pull-request reads never\n\t * reach them. This fills that gap in a single request for the whole repository, rather than a\n\t * per-pull-request enrichment that would scale with the list.\n\t *\n\t * `undefined` means unavailable (not enrolled in the preview, or not connected) as distinct from an\n\t * empty map, which means the repository genuinely has no stacks.\n\t */\n\toverride async getStacksByPullRequestNumber(\n\t\towner: string,\n\t\trepo: string,\n\t\tcancellation?: AbortSignal,\n\t): Promise<Map<number, PullRequestStackInfo> | undefined> {\n\t\t// The shared read path — it refreshes an expired session before use, which a bare `getSession()`\n\t\t// does not (it returns the cached session verbatim once one exists, expired or not).\n\t\tconst session = await this.resolveReadSession(undefined, undefined);\n\t\tif (session == null) return undefined;\n\n\t\tconst stacks = await (\n\t\t\tawait this.authenticationService.apis.github\n\t\t)?.getRepositoryStacks(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\towner,\n\t\t\trepo,\n\t\t\t{\n\t\t\t\tbaseUrl: this.apiBaseUrl,\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t\tif (stacks == null) return undefined;\n\n\t\tconst byNumber = new Map<number, PullRequestStackInfo>();\n\t\tfor (const stack of stacks) {\n\t\t\t// Defensive: this is a public-preview payload reaching us through an unvalidated cast, and a\n\t\t\t// malformed entry must cost its own stack's badges, not the whole panel.\n\t\t\tconst members = stack?.pull_requests;\n\t\t\tconst baseRef = stack?.base?.ref;\n\t\t\tif (members == null || baseRef == null) continue;\n\n\t\t\t// `pull_requests` is ordered bottom to top, and `position` is 1-based from the bottom.\n\t\t\tmembers.forEach((pr, i) => {\n\t\t\t\tbyNumber.set(pr.number, {\n\t\t\t\t\tid: stack.id,\n\t\t\t\t\tnumber: stack.number,\n\t\t\t\t\tsize: members.length,\n\t\t\t\t\tposition: i + 1,\n\t\t\t\t\tbaseRef: baseRef,\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\n\t\treturn byNumber;\n\t}\n\n\tprotected override async mergeProviderPullRequest(\n\t\tsession: ProviderAuthenticationSession,\n\t\tpr: PullRequest,\n\t\toptions?: {\n\t\t\tmergeMethod?: PullRequestMergeMethod;\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<boolean> {\n\t\tconst id = pr.nodeId;\n\t\tconst headRefSha = pr.refs?.head?.sha;\n\t\tif (id == null || headRefSha == null) return false;\n\n\t\tconst api = await this.authenticationService.apis.github;\n\n\t\t// GitHub rejects stacked pull requests on the legacy merge mutation, so they take the\n\t\t// asynchronous merge instead — which also lands every layer below this one.\n\t\tif (pr.stack != null) {\n\t\t\treturn (\n\t\t\t\t(await api?.mergeStackedPullRequest(\n\t\t\t\t\tthis,\n\t\t\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\t\t\tpr.repository.owner,\n\t\t\t\t\tpr.repository.repo,\n\t\t\t\t\tNumber(pr.id),\n\t\t\t\t\theadRefSha,\n\t\t\t\t\t{\n\t\t\t\t\t\tmergeMethod: options?.mergeMethod,\n\t\t\t\t\t\tbaseUrl: this.apiBaseUrl,\n\t\t\t\t\t},\n\t\t\t\t\tcancellation,\n\t\t\t\t)) ?? false\n\t\t\t);\n\t\t}\n\n\t\treturn (\n\t\t\tapi?.mergePullRequest(\n\t\t\t\tthis,\n\t\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\t\tid,\n\t\t\t\theadRefSha,\n\t\t\t\t{\n\t\t\t\t\tmergeMethod: options?.mergeMethod,\n\t\t\t\t\tbaseUrl: this.apiBaseUrl,\n\t\t\t\t},\n\t\t\t\tcancellation,\n\t\t\t) ?? false\n\t\t);\n\t}\n\n\tprotected override async getProviderCurrentAccount(\n\t\tsession: ProviderAuthenticationSession,\n\t\toptions?: { avatarSize?: number },\n\t): Promise<Account | undefined> {\n\t\treturn (await this.authenticationService.apis.github)?.getCurrentAccount(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\t{\n\t\t\t\t...options,\n\t\t\t\tbaseUrl: this.apiBaseUrl,\n\t\t\t},\n\t\t);\n\t}\n\n\tprotected override getProviderPullRequestIdentityFromMaybeUrl(search: string): PullRequestUrlIdentity | undefined {\n\t\treturn getGitHubPullRequestIdentityFromMaybeUrl(search, this.id);\n\t}\n}\n\nexport class GitHubIntegration extends GitHubIntegrationBase<GitCloudHostIntegrationId.GitHub> {\n\treadonly authProvider = authProvider;\n\treadonly id = GitCloudHostIntegrationId.GitHub;\n\tprotected readonly key = this.id;\n\treadonly name: string = 'GitHub';\n\tget domain(): string {\n\t\treturn metadata.domain;\n\t}\n\n\tprotected override get apiBaseUrl(): string | undefined {\n\t\t// Undefined on purpose, NOT 'https://api.github.com'. `@gitkraken/provider-apis` treats this value as an\n\t\t// *enterprise* base and derives both endpoints from it by appending GitHub Enterprise's paths:\n\t\t// `getRESTBaseUrl` appends `/api/v3` and `getGraphQLEndpoint` appends `/api/graphql` (githubHelpers.ts).\n\t\t// Handing it the cloud host therefore built `https://api.github.com/api/graphql`, which GitHub answers\n\t\t// 404 — every cloud GraphQL read (orgs, repos, PR/issue search) failed as `not-found`. Omitting it is\n\t\t// what selects the cloud endpoints (`GITHUB_API_URL` / `GITHUB_GRAPHQL_API_URL`), so cloud must pass\n\t\t// nothing and only GHE passes its instance base.\n\t\treturn undefined;\n\t}\n\n\toverride access(): Promise<boolean> {\n\t\t// Always allow GitHub cloud integration access\n\t\treturn Promise.resolve(true);\n\t}\n\n\t// This is a special case for GitHub because we use VSCode's GitHub session, and it can be disconnected\n\t// outside of the extension.\n\toverride async refresh(): Promise<void> {\n\t\tconst authProvider = await this.authenticationService.get(this.authProvider.id);\n\t\tconst session = await authProvider.getSession(this.authProviderDescriptor);\n\t\tif (session == null && this.maybeConnected) {\n\t\t\tvoid this.disconnect({ silent: true });\n\t\t} else {\n\t\t\tif (session?.accessToken !== this._session?.accessToken) {\n\t\t\t\tthis._session = undefined;\n\t\t\t}\n\t\t\tsuper.refresh();\n\t\t}\n\t}\n}\n\nexport class GitHubEnterpriseIntegration extends GitHubIntegrationBase<GitSelfManagedHostIntegrationId.CloudGitHubEnterprise> {\n\treadonly authProvider = cloudEnterpriseAuthProvider;\n\treadonly id = GitSelfManagedHostIntegrationId.CloudGitHubEnterprise;\n\tprotected readonly key;\n\treadonly name = 'GitHub Enterprise';\n\tget domain(): string {\n\t\treturn this._domain;\n\t}\n\n\tprotected override get apiBaseUrl(): string {\n\t\treturn `https://${this._domain}/api/v3`;\n\t}\n\n\tconstructor(\n\t\tctx: IntegrationServiceContext,\n\t\tauthenticationService: IntegrationAuthenticationService,\n\t\tgetProvidersApi: () => Promise<ProvidersApi>,\n\t\tdidChangeConnection: Emitter<IntegrationConnectionChangeEvent>,\n\t\tprivate readonly _domain: string,\n\t) {\n\t\tsuper(ctx, authenticationService, getProvidersApi, didChangeConnection);\n\t\tthis.key = `${this.id}:${this.domain}` as const;\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;AAwDA,SAAS,yBAAyB,OAA8C;CAC/E,IAAI,SAAS,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG,OAAO,CAAC;CAEhF,OAAO,OAAO,YACb,OAAO,QAAQ,KAAK,CAAC,CAAC,QACpB,CAAC,KAAK,YAAY,IAAI,WAAW,KAAK,OAAO,WAAW,YAAY,OAAO,WAAW,CACxF,CACD;AACD;AAEA,SAAS,4BAA4B,QAA0D;CAC9F,IAAI,CAAC,QAAQ,OAAO,CAAC;CAErB,IAAI;EACH,MAAM,SAAS,KAAK,MAAM,MAAM;EAChC,IAAI,UAAU,QAAQ,OAAO,WAAW,YAAY,CAAC,MAAM,QAAQ,MAAM,KAAK,aAAa,QAAQ;GAClG,MAAM,UAAU;GAChB,IAAI,QAAQ,SAAS,UACpB,OAAO,yBAAyB,QAAQ,OAAO;EAEjD;EAEA,OAAO,yBAAyB,MAAM;CACvC,QAAQ;EACP,OAAO,CAAC;CACT;AACD;AAEA,MAAM,WAAW,kBAAA;AACjB,MAAM,eAA4D,OAAO,OAAO;CAC/E,IAAI,SAAS;CACb,QAAQ,SAAS;AAClB,CAAC;AAED,MAAM,0BAA0B,kBAAA;AAChC,MAAM,8BAA2E,OAAO,OAAO;CAC9F,IAAI,wBAAwB;CAC5B,QAAQ,wBAAwB;AACjC,CAAC;;AAKD,MAAM,gCAAgC;AAEtC,IAAe,wBAAf,cAA8E,mBAG5E;CAQD,MAAyB,4BACxB,SACA,MACA,KACA,SAGoD;EACpD,QAAQ,MAAM,KAAK,sBAAsB,KAAK,OAAA,EAAS,oBACtD,MACA,gBAAgB,KAAK,IAAI,OAAO,GAChC,KAAK,OACL,KAAK,MACL,KACA;GACC,GAAG;GACH,SAAS,KAAK;EACf,CACD;CACD;CAEA,MAAyB,2BACxB,SACA,MACA,OACA,SAG+B;EAC/B,QAAQ,MAAM,KAAK,sBAAsB,KAAK,OAAA,EAAS,mBACtD,MACA,gBAAgB,KAAK,IAAI,OAAO,GAChC,KAAK,OACL,KAAK,MACL,OACA;GACC,GAAG;GACH,SAAS,KAAK;EACf,CACD;CACD;CAEA,MAAyB,mCACxB,SACA,MACA,QACiC;EACjC,MAAM,yBAAS,IAAI,IAAsB;EAEzC,MAAM,MAAM,MAAM,KAAK,sBAAsB,KAAK;EAClD,IAAI,OAAO,MAAM,OAAO;EAExB,MAAM,QAAQ,gBAAgB,KAAK,IAAI,OAAO;EAI9C,MAAM,+BAAe,IAAI,IAAoB;EAC7C,MAAM,YAAsB,CAAC;EAC7B,KAAK,MAAM,SAAS,QAAQ;GAC3B,MAAM,QAAQ,6BAA6B,KAAK,CAAC,EAAE;GACnD,IAAI,SAAS,MACZ,aAAa,IAAI,MAAM,YAAY,GAAG,KAAK;QAE3C,UAAU,KAAK,KAAK;EAEtB;EAEA,IAAI,UAAU,QAAQ;GACrB,MAAM,WAAW,MAAM,IAAI,qBAAqB,MAAM,OAAO,WAAW,EAAE,SAAS,KAAK,WAAW,CAAC;GACpG,KAAK,MAAM,CAAC,YAAY,UAAU,UACjC,aAAa,IAAI,YAAY,KAAK;EAEpC;EAIA,MAAM,8BAAc,IAAI,IAAsB;EAC9C,MAAM,MAAM,CAAC,GAAG,IAAI,IAAI,aAAa,OAAO,CAAC,CAAC,GAAG,+BAA+B,OAAM,UAAS;GAC9F,MAAM,OAAO,MAAM,IAAI,sBAAsB,MAAM,OAAO,OAAO,EAAE,SAAS,KAAK,WAAW,CAAC;GAC7F,YAAY,IACX,OACA,KAAK,KAAI,MAAK,EAAE,GAAG,CACpB;EACD,CAAC;EAED,KAAK,MAAM,CAAC,YAAY,UAAU,cACjC,OAAO,IAAI,YAAY,YAAY,IAAI,KAAK,KAAK,CAAC,CAAC;EAGpD,OAAO;CACR;CAEA,MAAyB,yBACxB,SACA,MACqC;EACrC,QAAQ,MAAM,KAAK,sBAAsB,KAAK,OAAA,EAAS,iBACtD,MACA,gBAAgB,KAAK,IAAI,OAAO,GAChC,KAAK,OACL,KAAK,MACL,EACC,SAAS,KAAK,WACf,CACD;CACD;CAEA,MAAyB,oCACxB,SACA,MACA,EAAE,MACwC;EAC1C,QAAQ,MAAM,KAAK,sBAAsB,KAAK,OAAA,EAAS,sBACtD,MACA,gBAAgB,KAAK,IAAI,OAAO,GAChC,KAAK,OACL,KAAK,MACL,OAAO,EAAE,GACT,EACC,SAAS,KAAK,WACf,CACD;CACD;CAEA,MAAyB,iBACxB,SACA,MACA,IAC6B;EAC7B,QAAQ,MAAM,KAAK,sBAAsB,KAAK,OAAA,EAAS,SACtD,MACA,gBAAgB,KAAK,IAAI,OAAO,GAChC,KAAK,OACL,KAAK,MACL,OAAO,EAAE,GACT;GACC,SAAS,KAAK;GACd,aAAa;EACd,CACD;CACD;CAEA,MAAyB,uBACxB,SACA,MACA,IACmC;EACnC,QAAQ,MAAM,KAAK,sBAAsB,KAAK,OAAA,EAAS,eACtD,MACA,gBAAgB,KAAK,IAAI,OAAO,GAChC,KAAK,OACL,KAAK,MACL,SAAS,IAAI,EAAE,GACf,EACC,SAAS,KAAK,WACf,CACD;CACD;CAEA,MAAyB,gCACxB,SACA,MACA,QACA,SAImC;EACnC,MAAM,EAAE,SAAS,GAAG,SAAS,WAAW,CAAC;EAEzC,MAAM,4BAA4B,MAAM;;GAA8C;EAAqB,CACzG;EACF,QAAQ,MAAM,KAAK,sBAAsB,KAAK,OAAA,EAAS,wBACtD,MACA,gBAAgB,KAAK,IAAI,OAAO,GAChC,KAAK,OACL,KAAK,MACL,QACA;GACC,GAAG;GACH,SAAS,SAAS,KAAI,MAAK,yBAAyB,CAAC,CAAC;GACtD,SAAS,KAAK;EACf,CACD;CACD;CAEA,MAAyB,gCACxB,SACA,MACA,KACmC;EACnC,QAAQ,MAAM,KAAK,sBAAsB,KAAK,OAAA,EAAS,wBACtD,MACA,gBAAgB,KAAK,IAAI,OAAO,GAChC,KAAK,OACL,KAAK,MACL,KACA,EACC,SAAS,KAAK,WACf,CACD;CACD;CAEA,MAAyB,8BACxB,SACA,MACA,cAC0C;EAC1C,QAAQ,MAAM,KAAK,sBAAsB,KAAK,OAAA,EAAS,sBACtD,MACA,gBAAgB,KAAK,IAAI,OAAO,GAChC,KAAK,OACL,KAAK,MACL,EACC,SAAS,KAAK,WACf,GACA,YACD;CACD;CAEA,MAAyB,gCACxB,SACqE;EAErE,MAAM,SAAS,OAAM,MADH,KAAK,gBAAgB,EAAA,CACd,4BAA4B,gBAAgB,KAAK,IAAI,OAAO,GAAG,EACvF,SAAS,KAAK,WACf,CAAC;EACD,OAAO;GACN,QAAQ,OAAO,OAAO,KAAI,OAAM;IAC/B,IAAI,EAAE;IACN,YAAY,KAAK;IACjB,MAAM,EAAE;IACR,KAAK,WAAW,KAAK,OAAO,GAAG,EAAE;GAClC,EAAE;GACF,GAAI,OAAO,YAAY,EAAE,WAAW,KAAK,IAAI,CAAC;GAC9C,GAAI,OAAO,YAAY,OAAO,EAAE,UAAU,OAAO,SAAS,IAAI,CAAC;EAChE;CACD;CAEA,MAAyB,8BACxB,SACA,KACA,SACmE;EAEnE,QAAO,MADW,KAAK,gBAAgB,EAAA,CAC5B,eAAe,gBAAgB,KAAK,IAAI,OAAO,GAAG,KAAK;GACjE,SAAS,KAAK;GACd,QAAQ,SAAS;EAClB,CAAC;CACF;CAEA,MAAyB,+BACxB,SACA,SACmE;EAInE,QAAO,MAHW,KAAK,gBAAgB,EAAA,CAG5B,uBAAuB,gBAAgB,KAAK,IAAI,OAAO,GAAG;GACpE,cAAc;IAAC;IAAS;IAAgB;GAAqB;GAC7D,SAAS,KAAK;GACd,QAAQ,SAAS;EAClB,CAAC;CACF;CAEA,MAAsB,YAAY,MAKU;EAC3C,MAAM,MAAM,MAAM,KAAK,gBAAgB;EAEvC,MAAM,UAAU,MAAM,KAAK,mBAAmB,KAAK,cAAc,KAAA,CAAS;EAC1E,IAAI,WAAW,MAAM,OAAO,KAAA;EAI5B,OAAO,IAAI,QAAQ,gBAAgB,KAAK,IAAI,OAAO,GAAG,KAAK,OAAO,KAAK,MAAM,KAAK,SAAS,EAC1F,SAAS,KAAK,WACf,CAAC;CACF;CAEA,MAAyB,6BACxB,SACA,OACA,cACA,SACqC;EACrC,QAAQ,MAAM,KAAK,sBAAsB,KAAK,OAAA,EAAS,qBACtD,MACA,gBAAgB,KAAK,IAAI,OAAO,GAChC;GACC,OAAO,OAAO,KAAI,MAAK,GAAG,EAAE,MAAM,GAAG,EAAE,MAAM;GAC7C,SAAS,KAAK;GACd,QAAQ,SAAS;GACjB,OAAO,SAAS;EACjB,GACA,YACD;CACD;CAEA,MAAyB,iCACxB,SACA,SAOmE;EACnE,MAAM,kBAAkB,SAAS,SAAS,SAAS,CAAC,GAAG,IAAI,IAAI,QAAQ,OAAO,CAAC,IAAI,KAAA;EASnF,MAAM,SAAS,MAAM,KAAK,sBAAsB,KAAK;EACrD,IAAI,UAAU,MAAM,OAAO,KAAA;EAE3B,MAAM,kBACL,SAAS,SAAS,QAAQ,QAAQ,MAAM,SAAS,IAAI,CAAC,GAAG,IAAI,IAAI,QAAQ,KAAK,CAAC,IAAI,CAAC,MAAM;EAC3F,MAAM,SACL,iBAAiB,UAAU,OACxB,gBAAgB,SAAQ,UACxB,gBAAgB,KAAI,YAAW;GAC9B,KAAK,GAAG,MAAM,GAAG;GACV;GACP,QAAQ,wCAAwC;EACjD,EAAE,CACH,IACC,gBAAgB,SAAQ,UAAS,CACjC;GAAE,KAAK;GAAc;GAAO,QAAQ,KAAA;EAAU,GAC9C,GAAI,SAAS,2BAA2B,OACrC,CACA;GACC,KAAK,GAAG,MAAM;GACP;GACP,QAAQ,wCAAA;EAGT,CACD,IACC,CAAC,CACL,CAAC;EACJ,MAAM,UAAU,4BAA4B,SAAS,MAAM;EAC3D,MAAM,0BAA0B,OAAO,KAAK,OAAO,CAAC,CAAC,WAAW;EAChE,MAAM,mBAAmB,OAAO,QAAO,UAAS,QAAQ,MAAM,QAAQ,IAAI;EAO1E,MAAM,gBACL,SAAS,UAAU,QAAQ,2BAA2B,iBAAiB,WAAW,IAC/E,mBACA;EACJ,MAAM,UAAU,MAAM,QAAQ,WAC7B,cAAc,IAAI,OAAM,WAAU;GACjC,KAAK,MAAM;GACX,QAAQ,MAAM,OAAO,yBAAyB,MAAM,gBAAgB,KAAK,IAAI,OAAO,GAAG;IACtF,SAAS,KAAK;IACd,OAAO,MAAM;IACb,QAAQ,QAAQ,MAAM;IACtB,SAAS,SAAS;IAClB,GAAI,MAAM,UAAU,OAAO;KAAE,QAAQ,MAAM;KAAQ,2BAA2B;IAAM,IAAI,KAAA;GACzF,CAAC;EACF,EAAE,CACH;EACA,IAAI,QAAQ,OAAM,WAAU,OAAO,WAAW,UAAU,GAAG;GAC1D,MAAM,QAAQ,QAAQ;GACtB,IAAI,OAAO,WAAW,YAAY,MAAM,MAAM;EAC/C;EAEA,MAAM,yBAAS,IAAI,IAAiC;EACpD,MAAM,cAA4C,CAAC;EACnD,MAAM,WAAW,CAAC;EAClB,IAAI,UAAU;EACd,IAAI,YAAY;EAChB,IAAI,2BAA2B;EAC/B,IAAI,qBAAqB;EACzB,KAAK,MAAM,WAAW,SAAS;GAC9B,IAAI,QAAQ,WAAW,YAAY;IAClC,SAAS,KAAK,yBAAyB,EAAE,YAAY,KAAK,GAAG,GAAG,QAAQ,MAAM,CAAC;IAC/E,YAAY;IACZ;GACD;GAEA,MAAM,EAAE,KAAK,WAAW,QAAQ;GAChC,KAAK,MAAM,MAAM,OAAO,QAAQ;IAC/B,MAAM,SAAS,sBAAsB,EAAE;IACvC,MAAM,WAAW,+BAA+B,MAAM,KAAK,WAAW;IACtE,IAAI,CAAC,OAAO,IAAI,QAAQ,GACvB,OAAO,IAAI,UAAU,MAAM;GAE7B;GACA,IAAI,OAAO,SAAS;IACnB,IAAI,OAAO,UAAU,QAAQ,OAAO,WAAW,QAAQ,OAAO,WAAW,QAAQ,MAAM;KACtF,YAAY;KACZ,2BAA2B;IAC5B,OAAO;KACN,UAAU;KACV,YAAY,OAAO,OAAO;IAC3B;GACD;GACA,IAAI,OAAO,WACV,YAAY;EAEd;EAEA,OAAO;GACN,QAAQ,CAAC,GAAG,OAAO,OAAO,CAAC;GAC3B,QAAQ;IACP,MAAM;IACN,QAAQ,UAAU,KAAK,UAAU;KAAE,MAAM;KAAU,SAAS;IAAY,CAAC,IAAI;IAC7E,WAAW,aAAa,KAAA;GACzB;GACA,GAAI,SAAS,UAAU,2BACpB,EACA,UAAU;IACT,cAAc;IACd,GAAI,SAAS,SAAS,EAAY,SAAS,IAAI,CAAC;GACjD,EACD,IACC,KAAA;EACJ;CACD;CAEA,MAAyB,uBACxB,SACA,OACA,cACoC;EACpC,QAAQ,MAAM,KAAK,qCAAqC,SAAS,OAAO,YAAY,EAAA,EAAI;CACzF;;;;;;;;CASA,MAAyB,qCACxB,SACA,OACA,cACA,SACoE;EAKpE,KAAK,SAAS,QAAQ,MAAM,WAAW,MAAM,SAAS,qBACrD,MAAM,IAAI,gCACT,KAAK,MACL,8GACD;EAGD,QAAQ,MAAM,KAAK,sBAAsB,KAAK,OAAA,EAAS,eACtD,MACA,gBAAgB,KAAK,IAAI,OAAO,GAChC;GACC,OAAO,OAAO,KAAI,MAAK,GAAG,EAAE,MAAM,GAAG,EAAE,MAAM;GAC7C,SAAS,KAAK;GACd,aAAa;GACb,qBAAqB,SAAS;GAC9B,QAAQ,SAAS;GACjB,UAAU,SAAS;GACnB,MAAM,SAAS;GACf,YAAY,SAAS,SAAS,SAC3B;IACA,UAAU,QAAQ,QAAQ,SAAA,QAA2B;IACrD,UAAU,QAAQ,QAAQ,SAAA,UAA6B;IACvD,WAAW,QAAQ,QAAQ,SAAA,SAA4B;GACxD,IACC,KAAA;EACJ,GACA,YACD;CACD;;;;;;CAOA,MAAyB,+BACxB,SACA,SAQA,cACqD;EACrD,QAAQ,MAAM,KAAK,sBAAsB,KAAK,OAAA,EAAS,uBACtD,MACA,gBAAgB,KAAK,IAAI,OAAO,GAChC;GACC,OAAO,QAAQ,OAAO,KAAI,MAAK,GAAG,EAAE,UAAU,GAAG,EAAE,MAAM;GACzD,KAAK,QAAQ;GACb,UAAU,QAAQ;GAClB,SAAS,KAAK;GACd,QAAQ,QAAQ;GAChB,UAAU,QAAQ;GAClB,SAAS,QAAQ;EAClB,GACA,YACD;CACD;;;;;;;;CASA,MAAyB,yBACxB,SACA,SAOA,cAC+C;EAC/C,QAAQ,MAAM,KAAK,sBAAsB,KAAK,OAAA,EAAS,iBACtD,MACA,gBAAgB,KAAK,IAAI,OAAO,GAChC;GAEC,OAAO,QAAQ,OAAO,KAAI,MAAK,GAAG,EAAE,UAAU,GAAG,EAAE,MAAM;GACzD,KAAK,QAAQ;GACb,UAAU,QAAQ;GAClB,SAAS,KAAK;GACd,aAAa;GACb,QAAQ,QAAQ;GAChB,UAAU,QAAQ;EACnB,GACA,YACD;CACD;;;;;CAMA,MAAyB,oBACxB,SACA,QACA,cAC8C;EAC9C,QAAQ,MAAM,KAAK,sBAAsB,KAAK,OAAA,EAAS,YACtD,MACA,gBAAgB,KAAK,IAAI,OAAO,GAChC,OAAO,KAAI,OAAM;GAChB,OAAO,EAAE,OAAO,KAAI,MAAK,GAAG,EAAE,UAAU,GAAG,EAAE,MAAM;GACnD,KAAK,EAAE;GACP,UAAU,EAAE;EACb,EAAE,GACF,EAAE,SAAS,KAAK,WAAW,GAC3B,YACD;CACD;;;;;CAMA,MAAyB,uBACxB,SACA,aACA,cACkD;EAClD,QAAQ,MAAM,KAAK,sBAAsB,KAAK,OAAA,EAAS,eACtD,MACA,gBAAgB,KAAK,IAAI,OAAO,GAChC,aACA;GAAE,SAAS,KAAK;GAAY,aAAa;EAAK,GAC9C,YACD;CACD;;;;;CAMA,MAAyB,0BACxB,SACA,QACA,cAC8C;EAC9C,QAAQ,MAAM,KAAK,sBAAsB,KAAK,OAAA,EAAS,kBACtD,MACA,gBAAgB,KAAK,IAAI,OAAO,GAChC,OAAO,KAAI,OAAM;GAChB,OAAO,EAAE,OAAO,KAAI,MAAK,GAAG,EAAE,UAAU,GAAG,EAAE,MAAM;GACnD,KAAK,EAAE;GACP,UAAU,EAAE;EACb,EAAE,GACF,EAAE,SAAS,KAAK,WAAW,GAC3B,YACD;CACD;CAEA,MAAyB,2BACxB,SACA,aACA,OACA,cACA,SACqC;EACrC,QAAQ,MAAM,KAAK,sBAAsB,KAAK,OAAA,EAAS,mBACtD,MACA,gBAAgB,KAAK,IAAI,OAAO,GAChC;GACC,QAAQ;GACR,OAAO,OAAO,KAAI,MAAK,GAAG,EAAE,MAAM,GAAG,EAAE,MAAM;GAC7C,SAAS,KAAK;GACd,GAAG;EACJ,GACA,YACD;CACD;;;;;;;;;;;;CAaA,MAAe,6BACd,OACA,MACA,cACyD;EAGzD,MAAM,UAAU,MAAM,KAAK,mBAAmB,KAAA,GAAW,KAAA,CAAS;EAClE,IAAI,WAAW,MAAM,OAAO,KAAA;EAE5B,MAAM,SAAS,OACd,MAAM,KAAK,sBAAsB,KAAK,OAAA,EACpC,oBACF,MACA,gBAAgB,KAAK,IAAI,OAAO,GAChC,OACA,MACA,EACC,SAAS,KAAK,WACf,GACA,YACD;EACA,IAAI,UAAU,MAAM,OAAO,KAAA;EAE3B,MAAM,2BAAW,IAAI,IAAkC;EACvD,KAAK,MAAM,SAAS,QAAQ;GAG3B,MAAM,UAAU,OAAO;GACvB,MAAM,UAAU,OAAO,MAAM;GAC7B,IAAI,WAAW,QAAQ,WAAW,MAAM;GAGxC,QAAQ,SAAS,IAAI,MAAM;IAC1B,SAAS,IAAI,GAAG,QAAQ;KACvB,IAAI,MAAM;KACV,QAAQ,MAAM;KACd,MAAM,QAAQ;KACd,UAAU,IAAI;KACL;IACV,CAAC;GACF,CAAC;EACF;EAEA,OAAO;CACR;CAEA,MAAyB,yBACxB,SACA,IACA,SAGA,cACmB;EACnB,MAAM,KAAK,GAAG;EACd,MAAM,aAAa,GAAG,MAAM,MAAM;EAClC,IAAI,MAAM,QAAQ,cAAc,MAAM,OAAO;EAE7C,MAAM,MAAM,MAAM,KAAK,sBAAsB,KAAK;EAIlD,IAAI,GAAG,SAAS,MACf,OACE,MAAM,KAAK,wBACX,MACA,gBAAgB,KAAK,IAAI,OAAO,GAChC,GAAG,WAAW,OACd,GAAG,WAAW,MACd,OAAO,GAAG,EAAE,GACZ,YACA;GACC,aAAa,SAAS;GACtB,SAAS,KAAK;EACf,GACA,YACD,KAAM;EAIR,OACC,KAAK,iBACJ,MACA,gBAAgB,KAAK,IAAI,OAAO,GAChC,IACA,YACA;GACC,aAAa,SAAS;GACtB,SAAS,KAAK;EACf,GACA,YACD,KAAK;CAEP;CAEA,MAAyB,0BACxB,SACA,SAC+B;EAC/B,QAAQ,MAAM,KAAK,sBAAsB,KAAK,OAAA,EAAS,kBACtD,MACA,gBAAgB,KAAK,IAAI,OAAO,GAChC;GACC,GAAG;GACH,SAAS,KAAK;EACf,CACD;CACD;CAEA,2CAA8D,QAAoD;EACjH,OAAO,yCAAyC,QAAQ,KAAK,EAAE;CAChE;AACD;AAEA,IAAa,oBAAb,cAAuC,sBAAwD;CAC9F,eAAwB;CACxB,KAAS;CACT,MAAyB,KAAK;CAC9B,OAAwB;CACxB,IAAI,SAAiB;EACpB,OAAO,SAAS;CACjB;CAEA,IAAuB,aAAiC,CASxD;CAEA,SAAoC;EAEnC,OAAO,QAAQ,QAAQ,IAAI;CAC5B;CAIA,MAAe,UAAyB;EAEvC,MAAM,UAAU,OAAM,MADK,KAAK,sBAAsB,IAAI,KAAK,aAAa,EAAE,EAAA,CAC3C,WAAW,KAAK,sBAAsB;EACzE,IAAI,WAAW,QAAQ,KAAK,gBAC3B,KAAU,WAAW,EAAE,QAAQ,KAAK,CAAC;OAC/B;GACN,IAAI,SAAS,gBAAgB,KAAK,UAAU,aAC3C,KAAK,WAAW,KAAA;GAEjB,MAAM,QAAQ;EACf;CACD;AACD;AAEA,IAAa,8BAAb,cAAiD,sBAA6E;CAkB3G;CAjBlB,eAAwB;CACxB,KAAS;CACT;CACA,OAAgB;CAChB,IAAI,SAAiB;EACpB,OAAO,KAAK;CACb;CAEA,IAAuB,aAAqB;EAC3C,OAAO,WAAW,KAAK,QAAQ;CAChC;CAEA,YACC,KACA,uBACA,iBACA,qBACA,SACC;EACD,MAAM,KAAK,uBAAuB,iBAAiB,mBAAmB;EAFrD,KAAA,UAAA;EAGjB,KAAK,MAAM,GAAG,KAAK,GAAG,GAAG,KAAK;CAC/B;AACD"}
|
|
1
|
+
{"version":3,"file":"github.js","names":[],"sources":["../../../../../plus/integrations/src/providers/github.ts"],"sourcesContent":["import { gitHubPullRequestRelationshipQualifiers } from '@gitlens/git-github/api/pullRequestSearchQuery.js';\nimport type { Account, UnidentifiedAuthor } from '@gitlens/git/models/author.js';\nimport type { DefaultBranch } from '@gitlens/git/models/defaultBranch.js';\nimport type { Issue, IssueSearchCriteria, IssueShape } from '@gitlens/git/models/issue.js';\nimport type { IssueOrPullRequest } from '@gitlens/git/models/issueOrPullRequest.js';\nimport type {\n\tPullRequest,\n\tPullRequestMergeMethod,\n\tPullRequestSearchCriteria,\n\tPullRequestStackInfo,\n\tPullRequestState,\n\tPullRequestStateFilter,\n} from '@gitlens/git/models/pullRequest.js';\nimport type { RepositoryMetadata } from '@gitlens/git/models/repositoryMetadata.js';\nimport type { RepositoryDescriptor } from '@gitlens/git/models/resourceDescriptor.js';\nimport { getGitHubNoReplyAddressParts } from '@gitlens/git/remotes/github.js';\nimport type { PullRequestUrlIdentity } from '@gitlens/git/utils/pullRequest.utils.js';\nimport type { Emitter } from '@gitlens/utils/event.js';\nimport { batch } from '@gitlens/utils/promise.js';\nimport type { IntegrationAuthenticationProviderDescriptor } from '../authentication/integrationAuthenticationProvider.js';\nimport type { IntegrationAuthenticationService } from '../authentication/integrationAuthenticationService.js';\nimport type { ProviderAuthenticationSession } from '../authentication/models.js';\nimport { toTokenWithInfo } from '../authentication/models.js';\nimport { toCollectionScopeFailure } from '../collectionMetadata.js';\nimport { GitCloudHostIntegrationId, GitSelfManagedHostIntegrationId } from '../constants.js';\nimport type { IntegrationServiceContext } from '../context.js';\nimport { IntegrationReadUnavailableError } from '../errors.js';\nimport type { IntegrationConnectionChangeEvent } from '../integrationService.js';\nimport type { SearchMyPullRequestsOptions, SearchPullRequestsOptions } from '../models/gitHostIntegration.js';\nimport { GitHostIntegration } from '../models/gitHostIntegration.js';\nimport type {\n\tProviderIssueSearchPage,\n\tProviderPullRequestCount,\n\tProviderPullRequestSearchPage,\n\tSearchMyIssuesOptions,\n} from '../models/integration.js';\nimport type { GitHubIntegrationIds } from './github/github.utils.js';\nimport { getGitHubPullRequestIdentityFromMaybeUrl } from './github/github.utils.js';\nimport type {\n\tProviderApiPagedResult,\n\tProviderHierarchyResult,\n\tProviderOrganization,\n\tProviderPullRequest,\n\tProviderRepoInput,\n\tProviderRepository,\n} from './models.js';\nimport {\n\tgetProviderPullRequestIdentity,\n\tIssueFilter,\n\tprovidersMetadata,\n\tPullRequestFilter,\n\ttoProviderPullRequest,\n} from './models.js';\nimport type { ProvidersApi } from './providersApi.js';\n\ntype GitHubPullRequestFacetCursor = Record<string, string>;\n\nfunction toPullRequestFacetCursor(value: unknown): GitHubPullRequestFacetCursor {\n\tif (value == null || typeof value !== 'object' || Array.isArray(value)) return {};\n\n\treturn Object.fromEntries(\n\t\tObject.entries(value).filter(\n\t\t\t([key, cursor]) => key.length !== 0 && typeof cursor === 'string' && cursor.length !== 0,\n\t\t),\n\t);\n}\n\nfunction parsePullRequestFacetCursor(cursor: string | undefined): GitHubPullRequestFacetCursor {\n\tif (!cursor) return {};\n\n\ttry {\n\t\tconst parsed = JSON.parse(cursor) as unknown;\n\t\tif (parsed != null && typeof parsed === 'object' && !Array.isArray(parsed) && 'cursors' in parsed) {\n\t\t\tconst wrapped = parsed as { type?: unknown; cursors?: unknown };\n\t\t\tif (wrapped.type === 'cursor') {\n\t\t\t\treturn toPullRequestFacetCursor(wrapped.cursors);\n\t\t\t}\n\t\t}\n\n\t\treturn toPullRequestFacetCursor(parsed);\n\t} catch {\n\t\treturn {};\n\t}\n}\n\nconst metadata = providersMetadata[GitCloudHostIntegrationId.GitHub];\nconst authProvider: IntegrationAuthenticationProviderDescriptor = Object.freeze({\n\tid: metadata.id,\n\tscopes: metadata.scopes,\n});\n\nconst cloudEnterpriseMetadata = providersMetadata[GitSelfManagedHostIntegrationId.CloudGitHubEnterprise];\nconst cloudEnterpriseAuthProvider: IntegrationAuthenticationProviderDescriptor = Object.freeze({\n\tid: cloudEnterpriseMetadata.id,\n\tscopes: cloudEnterpriseMetadata.scopes,\n});\n\nexport type GitHubRepositoryDescriptor = RepositoryDescriptor;\n\n/** How many per-login SSH signing-key lookups to run concurrently, to avoid a request burst that trips rate limiting. */\nconst sshSigningKeyResolveBatchSize = 10;\n\nabstract class GitHubIntegrationBase<ID extends GitHubIntegrationIds> extends GitHostIntegration<\n\tID,\n\tGitHubRepositoryDescriptor\n> {\n\t/**\n\t * Base URL handed to `@gitkraken/provider-apis`, which derives BOTH the REST and the GraphQL endpoint from it\n\t * by appending GitHub Enterprise's paths. Only a GHE instance base belongs here; cloud passes `undefined`,\n\t * the sole value that selects the cloud endpoints (see the cloud subclass).\n\t */\n\tprotected abstract apiBaseUrlFor(session: ProviderAuthenticationSession): string | undefined;\n\n\tprotected override async getProviderAccountForCommit(\n\t\tsession: ProviderAuthenticationSession,\n\t\trepo: GitHubRepositoryDescriptor,\n\t\trev: string,\n\t\toptions?: {\n\t\t\tavatarSize?: number;\n\t\t},\n\t): Promise<Account | UnidentifiedAuthor | undefined> {\n\t\treturn (await this.authenticationService.apis.github)?.getAccountForCommit(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\trepo.owner,\n\t\t\trepo.name,\n\t\t\trev,\n\t\t\t{\n\t\t\t\t...options,\n\t\t\t\tbaseUrl: this.apiBaseUrlFor(session),\n\t\t\t},\n\t\t);\n\t}\n\n\tprotected override async getProviderAccountForEmail(\n\t\tsession: ProviderAuthenticationSession,\n\t\trepo: GitHubRepositoryDescriptor,\n\t\temail: string,\n\t\toptions?: {\n\t\t\tavatarSize?: number;\n\t\t},\n\t): Promise<Account | undefined> {\n\t\treturn (await this.authenticationService.apis.github)?.getAccountForEmail(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\trepo.owner,\n\t\t\trepo.name,\n\t\t\temail,\n\t\t\t{\n\t\t\t\t...options,\n\t\t\t\tbaseUrl: this.apiBaseUrlFor(session),\n\t\t\t},\n\t\t);\n\t}\n\n\tprotected override async getProviderSshSigningKeysForEmails(\n\t\tsession: ProviderAuthenticationSession,\n\t\trepo: GitHubRepositoryDescriptor,\n\t\temails: string[],\n\t): Promise<Map<string, string[]>> {\n\t\tconst result = new Map<string, string[]>();\n\n\t\tconst api = await this.authenticationService.apis.github;\n\t\tif (api == null) return result;\n\n\t\tconst token = toTokenWithInfo(this.id, session);\n\n\t\t// Resolve each email to a login: GitHub noreply addresses encode it locally; the rest are resolved in a single\n\t\t// batched GraphQL request rather than one round-trip per email.\n\t\tconst loginByEmail = new Map<string, string>();\n\t\tconst toResolve: string[] = [];\n\t\tfor (const email of emails) {\n\t\t\tconst login = getGitHubNoReplyAddressParts(email)?.login;\n\t\t\tif (login != null) {\n\t\t\t\tloginByEmail.set(email.toLowerCase(), login);\n\t\t\t} else {\n\t\t\t\ttoResolve.push(email);\n\t\t\t}\n\t\t}\n\n\t\tif (toResolve.length) {\n\t\t\tconst resolved = await api.getAccountsForEmails(this, token, toResolve, {\n\t\t\t\tbaseUrl: this.apiBaseUrlFor(session),\n\t\t\t});\n\t\t\tfor (const [emailLower, login] of resolved) {\n\t\t\t\tloginByEmail.set(emailLower, login);\n\t\t\t}\n\t\t}\n\n\t\t// Fetch signing keys once per distinct login (REST has no batch endpoint), in bounded batches rather than firing\n\t\t// all lookups at once, to avoid a request burst that could trip secondary rate limiting. Then map keys to each email.\n\t\tconst keysByLogin = new Map<string, string[]>();\n\t\tawait batch([...new Set(loginByEmail.values())], sshSigningKeyResolveBatchSize, async login => {\n\t\t\tconst keys = await api.getUserSshSigningKeys(this, token, login, { baseUrl: this.apiBaseUrlFor(session) });\n\t\t\tkeysByLogin.set(\n\t\t\t\tlogin,\n\t\t\t\tkeys.map(k => k.key),\n\t\t\t);\n\t\t});\n\n\t\tfor (const [emailLower, login] of loginByEmail) {\n\t\t\tresult.set(emailLower, keysByLogin.get(login) ?? []);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tprotected override async getProviderDefaultBranch(\n\t\tsession: ProviderAuthenticationSession,\n\t\trepo: GitHubRepositoryDescriptor,\n\t): Promise<DefaultBranch | undefined> {\n\t\treturn (await this.authenticationService.apis.github)?.getDefaultBranch(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\trepo.owner,\n\t\t\trepo.name,\n\t\t\t{\n\t\t\t\tbaseUrl: this.apiBaseUrlFor(session),\n\t\t\t},\n\t\t);\n\t}\n\n\tprotected override async getProviderLinkedIssueOrPullRequest(\n\t\tsession: ProviderAuthenticationSession,\n\t\trepo: GitHubRepositoryDescriptor,\n\t\t{ id }: { id: string; key: string },\n\t): Promise<IssueOrPullRequest | undefined> {\n\t\treturn (await this.authenticationService.apis.github)?.getIssueOrPullRequest(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\trepo.owner,\n\t\t\trepo.name,\n\t\t\tNumber(id),\n\t\t\t{\n\t\t\t\tbaseUrl: this.apiBaseUrlFor(session),\n\t\t\t},\n\t\t);\n\t}\n\n\tprotected override async getProviderIssue(\n\t\tsession: ProviderAuthenticationSession,\n\t\trepo: GitHubRepositoryDescriptor,\n\t\tid: string,\n\t): Promise<Issue | undefined> {\n\t\treturn (await this.authenticationService.apis.github)?.getIssue(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\trepo.owner,\n\t\t\trepo.name,\n\t\t\tNumber(id),\n\t\t\t{\n\t\t\t\tbaseUrl: this.apiBaseUrlFor(session),\n\t\t\t\tincludeBody: true,\n\t\t\t},\n\t\t);\n\t}\n\n\tprotected override async getProviderPullRequest(\n\t\tsession: ProviderAuthenticationSession,\n\t\trepo: GitHubRepositoryDescriptor,\n\t\tid: string,\n\t): Promise<PullRequest | undefined> {\n\t\treturn (await this.authenticationService.apis.github)?.getPullRequest(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\trepo.owner,\n\t\t\trepo.name,\n\t\t\tparseInt(id, 10),\n\t\t\t{\n\t\t\t\tbaseUrl: this.apiBaseUrlFor(session),\n\t\t\t},\n\t\t);\n\t}\n\n\tprotected override async getProviderPullRequestForBranch(\n\t\tsession: ProviderAuthenticationSession,\n\t\trepo: GitHubRepositoryDescriptor,\n\t\tbranch: string,\n\t\toptions?: {\n\t\t\tavatarSize?: number;\n\t\t\tinclude?: PullRequestState[];\n\t\t},\n\t): Promise<PullRequest | undefined> {\n\t\tconst { include, ...opts } = options ?? {};\n\n\t\tconst toGitHubPullRequestState = (await import(/* webpackChunkName: \"integrations\" */ './github/models.js'))\n\t\t\t.toGitHubPullRequestState;\n\t\treturn (await this.authenticationService.apis.github)?.getPullRequestForBranch(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\trepo.owner,\n\t\t\trepo.name,\n\t\t\tbranch,\n\t\t\t{\n\t\t\t\t...opts,\n\t\t\t\tinclude: include?.map(s => toGitHubPullRequestState(s)),\n\t\t\t\tbaseUrl: this.apiBaseUrlFor(session),\n\t\t\t},\n\t\t);\n\t}\n\n\tprotected override async getProviderPullRequestForCommit(\n\t\tsession: ProviderAuthenticationSession,\n\t\trepo: GitHubRepositoryDescriptor,\n\t\trev: string,\n\t): Promise<PullRequest | undefined> {\n\t\treturn (await this.authenticationService.apis.github)?.getPullRequestForCommit(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\trepo.owner,\n\t\t\trepo.name,\n\t\t\trev,\n\t\t\t{\n\t\t\t\tbaseUrl: this.apiBaseUrlFor(session),\n\t\t\t},\n\t\t);\n\t}\n\n\tprotected override async getProviderRepositoryMetadata(\n\t\tsession: ProviderAuthenticationSession,\n\t\trepo: GitHubRepositoryDescriptor,\n\t\tcancellation?: AbortSignal,\n\t): Promise<RepositoryMetadata | undefined> {\n\t\treturn (await this.authenticationService.apis.github)?.getRepositoryMetadata(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\trepo.owner,\n\t\t\trepo.name,\n\t\t\t{\n\t\t\t\tbaseUrl: this.apiBaseUrlFor(session),\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\tprotected override async getProviderOrganizationsForUser(\n\t\tsession: ProviderAuthenticationSession,\n\t): Promise<ProviderHierarchyResult<ProviderOrganization> | undefined> {\n\t\tconst api = await this.getProvidersApi();\n\t\tconst result = await api.getGitHubOrgsForCurrentUser(toTokenWithInfo(this.id, session), {\n\t\t\tbaseUrl: this.apiBaseUrlFor(session),\n\t\t});\n\t\tconst webUrl =\n\t\t\tthis.id === GitSelfManagedHostIntegrationId.CloudGitHubEnterprise\n\t\t\t\t? this.getSelfManagedInstallationUrl(session)\n\t\t\t\t: `https://${this.domain}`;\n\t\treturn {\n\t\t\tvalues: result.values.map(o => ({\n\t\t\t\tid: o.id,\n\t\t\t\tproviderId: this.id,\n\t\t\t\tname: o.username,\n\t\t\t\turl: `${webUrl}/${o.username}`,\n\t\t\t})),\n\t\t\t...(result.truncated ? { truncated: true } : {}),\n\t\t\t...(result.metadata != null ? { metadata: result.metadata } : {}),\n\t\t};\n\t}\n\n\tprotected override async getProviderRepositoriesForOrg(\n\t\tsession: ProviderAuthenticationSession,\n\t\torg: string,\n\t\toptions?: { cursor?: string },\n\t): Promise<ProviderHierarchyResult<ProviderRepository> | undefined> {\n\t\tconst api = await this.getProvidersApi();\n\t\treturn api.getReposForOrg(toTokenWithInfo(this.id, session), org, {\n\t\t\tbaseUrl: this.apiBaseUrlFor(session),\n\t\t\tcursor: options?.cursor,\n\t\t});\n\t}\n\n\tprotected override async getProviderRepositoriesForUser(\n\t\tsession: ProviderAuthenticationSession,\n\t\toptions?: { cursor?: string },\n\t): Promise<ProviderHierarchyResult<ProviderRepository> | undefined> {\n\t\tconst api = await this.getProvidersApi();\n\t\t// `/user/repos` with the full affiliation set: the user's own repos, collaborations, and org-member\n\t\t// repos — matching gkcli's org-less `provider repos github` walk (not every repo of every org).\n\t\treturn api.getReposForCurrentUser(toTokenWithInfo(this.id, session), {\n\t\t\taffiliations: ['owner', 'collaborator', 'organization_member'],\n\t\t\tbaseUrl: this.apiBaseUrlFor(session),\n\t\t\tcursor: options?.cursor,\n\t\t});\n\t}\n\n\tpublic override async getRepoInfo(repo: {\n\t\towner: string;\n\t\tname: string;\n\t\tproject?: string;\n\t\tconnectionId?: string;\n\t}): Promise<ProviderRepository | undefined> {\n\t\tconst api = await this.getProvidersApi();\n\t\t// `connectionId` targets a specific account (multi-account); omitted reads the primary.\n\t\tconst session = await this.resolveReadSession(repo.connectionId, undefined);\n\t\tif (session == null) return undefined;\n\n\t\t// `apiBaseUrlFor` is undefined for cloud (which is what selects the cloud endpoints) and the GHE instance base\n\t\t// for enterprise (inherited override).\n\t\treturn api.getRepo(toTokenWithInfo(this.id, session), repo.owner, repo.name, repo.project, {\n\t\t\tbaseUrl: this.apiBaseUrlFor(session),\n\t\t});\n\t}\n\n\tprotected override async searchProviderMyPullRequests(\n\t\tsession: ProviderAuthenticationSession,\n\t\trepos?: GitHubRepositoryDescriptor[],\n\t\tcancellation?: AbortSignal,\n\t\toptions?: SearchMyPullRequestsOptions,\n\t): Promise<PullRequest[] | undefined> {\n\t\treturn (await this.authenticationService.apis.github)?.searchMyPullRequests(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\t{\n\t\t\t\trepos: repos?.map(r => `${r.owner}/${r.name}`),\n\t\t\t\tbaseUrl: this.apiBaseUrlFor(session),\n\t\t\t\tsilent: options?.silent,\n\t\t\t\tstate: options?.state,\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\tprotected override async getProviderMyPullRequestsForUser(\n\t\tsession: ProviderAuthenticationSession,\n\t\toptions?: {\n\t\t\tstate?: PullRequestStateFilter[];\n\t\t\tcursor?: string;\n\t\t\tincludeReviewRequested?: boolean;\n\t\t\tfilters?: PullRequestFilter[];\n\t\t\tsummary?: boolean;\n\t\t},\n\t): Promise<ProviderApiPagedResult<ProviderPullRequest> | undefined> {\n\t\tconst explicitFilters = options?.filters?.length ? [...new Set(options.filters)] : undefined;\n\t\t// Every account-wide read goes through our own facet search — there is deliberately no SDK\n\t\t// `getPullRequestsForUser` fallback. It could express neither a state set, nor exact relationships (its\n\t\t// `involves:` is a different question), nor the full projection, so which reads it could serve depended on\n\t\t// the options, and the two routes disagreed on more than they had to: only this one applies the Launchpad\n\t\t// ignored/included repository and organization qualifiers, so the same read returned different pull\n\t\t// requests depending on options that were supposed to affect only projection or relationship. With no\n\t\t// state and no filters this emits a single facet with no relationship qualifier, which is GitHub's own\n\t\t// `involves:@me` and `is:open` default — the same question the fallback asked, now on one route.\n\t\tconst github = await this.authenticationService.apis.github;\n\t\tif (github == null) return undefined;\n\n\t\tconst requestedStates: PullRequestStateFilter[] =\n\t\t\toptions?.state != null && options.state.length > 0 ? [...new Set(options.state)] : ['open'];\n\t\tconst facets =\n\t\t\texplicitFilters?.length != null\n\t\t\t\t? requestedStates.flatMap(state =>\n\t\t\t\t\t\texplicitFilters.map(filter => ({\n\t\t\t\t\t\t\tkey: `${state}:${filter}`,\n\t\t\t\t\t\t\tstate: state,\n\t\t\t\t\t\t\tsearch: gitHubPullRequestRelationshipQualifiers[filter],\n\t\t\t\t\t\t})),\n\t\t\t\t\t)\n\t\t\t\t: requestedStates.flatMap(state => [\n\t\t\t\t\t\t{ key: state, state: state, search: undefined },\n\t\t\t\t\t\t...(options?.includeReviewRequested === true\n\t\t\t\t\t\t\t? [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tkey: `${state}:${PullRequestFilter.ReviewRequested}`,\n\t\t\t\t\t\t\t\t\t\tstate: state,\n\t\t\t\t\t\t\t\t\t\tsearch: gitHubPullRequestRelationshipQualifiers[\n\t\t\t\t\t\t\t\t\t\t\tPullRequestFilter.ReviewRequested\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t: []),\n\t\t\t\t\t]);\n\t\tconst cursors = parsePullRequestFacetCursor(options?.cursor);\n\t\tconst hasResumableFacetCursor = Object.keys(cursors).length !== 0;\n\t\tconst facetsWithCursor = facets.filter(facet => cursors[facet.key] != null);\n\t\t// The first call has no cursor, so query every requested state. A continuation only happens after a\n\t\t// prior page reported `more:true`, whose bundle carries a cursor for each facet still in flight;\n\t\t// facets absent from the bundle are exhausted, so re-querying them from scratch would refetch the\n\t\t// same PRs (duplicated by the dedup-free sweep) and waste an API call per page. Query only the\n\t\t// states that still have a cursor, but degrade a malformed/empty cursor bundle, or one that doesn't\n\t\t// apply to the current requested states, to the first page rather than returning an empty page.\n\t\tconst facetsToQuery =\n\t\t\toptions?.cursor != null && hasResumableFacetCursor && facetsWithCursor.length !== 0\n\t\t\t\t? facetsWithCursor\n\t\t\t\t: facets;\n\t\tconst results = await Promise.allSettled(\n\t\t\tfacetsToQuery.map(async facet => ({\n\t\t\t\tkey: facet.key,\n\t\t\t\tresult: await github.searchMyPullRequestsPage(this, toTokenWithInfo(this.id, session), {\n\t\t\t\t\tbaseUrl: this.apiBaseUrlFor(session),\n\t\t\t\t\tstate: facet.state,\n\t\t\t\t\tcursor: cursors[facet.key],\n\t\t\t\t\tsummary: options?.summary,\n\t\t\t\t\t...(facet.search != null ? { search: facet.search, includeDefaultInvolvement: false } : undefined),\n\t\t\t\t}),\n\t\t\t})),\n\t\t);\n\t\tif (results.every(result => result.status === 'rejected')) {\n\t\t\tconst first = results[0];\n\t\t\tif (first?.status === 'rejected') throw first.reason;\n\t\t}\n\n\t\tconst values = new Map<string, ProviderPullRequest>();\n\t\tconst nextCursors: GitHubPullRequestFacetCursor = {};\n\t\tconst failures = [];\n\t\tlet hasMore = false;\n\t\tlet truncated = false;\n\t\tlet structuralIncompleteness = false;\n\t\tlet unkeyedPullRequest = 0;\n\t\tfor (const outcome of results) {\n\t\t\tif (outcome.status === 'rejected') {\n\t\t\t\tfailures.push(toCollectionScopeFailure({ providerId: this.id }, outcome.reason));\n\t\t\t\ttruncated = true;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst { key, result } = outcome.value;\n\t\t\tfor (const pr of result.values) {\n\t\t\t\tconst mapped = toProviderPullRequest(pr);\n\t\t\t\tconst identity = getProviderPullRequestIdentity(mapped) ?? `unkeyed:${unkeyedPullRequest++}`;\n\t\t\t\tif (!values.has(identity)) {\n\t\t\t\t\tvalues.set(identity, mapped);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (result.hasMore) {\n\t\t\t\tif (result.cursor == null || result.cursor === '{}' || result.cursor === cursors[key]) {\n\t\t\t\t\ttruncated = true;\n\t\t\t\t\tstructuralIncompleteness = true;\n\t\t\t\t} else {\n\t\t\t\t\thasMore = true;\n\t\t\t\t\tnextCursors[key] = result.cursor;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (result.truncated) {\n\t\t\t\ttruncated = true;\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tvalues: [...values.values()],\n\t\t\tpaging: {\n\t\t\t\tmore: hasMore,\n\t\t\t\tcursor: hasMore ? JSON.stringify({ type: 'cursor', cursors: nextCursors }) : '{}',\n\t\t\t\ttruncated: truncated || undefined,\n\t\t\t},\n\t\t\t...(failures.length || structuralIncompleteness\n\t\t\t\t? {\n\t\t\t\t\t\tmetadata: {\n\t\t\t\t\t\t\tcompleteness: 'partial' as const,\n\t\t\t\t\t\t\t...(failures.length ? { failures: failures } : {}),\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t: undefined),\n\t\t};\n\t}\n\n\tprotected override async searchProviderMyIssues(\n\t\tsession: ProviderAuthenticationSession,\n\t\trepos?: GitHubRepositoryDescriptor[],\n\t\tcancellation?: AbortSignal,\n\t): Promise<IssueShape[] | undefined> {\n\t\treturn (await this.searchProviderMyIssuesWithTruncation(session, repos, cancellation))?.values;\n\t}\n\n\t/**\n\t * GitHub's account-wide issue search pages authored/assigned/mentioned independently behind one composite\n\t * cursor. This variant preserves that cursor and the provider's 1,000-result search ceiling signal.\n\t *\n\t * `options.filters` selects which of those three searches run, so a caller can narrow the union to just its\n\t * own slice (e.g. `[Assignee]` ⇒ `assignee:@me`). Omitted keeps GitHub's own definition of \"mine\" (all three).\n\t */\n\tprotected override async searchProviderMyIssuesWithTruncation(\n\t\tsession: ProviderAuthenticationSession,\n\t\trepos?: GitHubRepositoryDescriptor[],\n\t\tcancellation?: AbortSignal,\n\t\toptions?: SearchMyIssuesOptions,\n\t): Promise<{ values: IssueShape[]; truncated: boolean } | undefined> {\n\t\t// `includeAllAssignees` becomes `assignee:*`, which needs a scope to mean anything — with none it matches\n\t\t// millions of issues across all of GitHub rather than \"assigned to anyone in the user's world\". ANY scope\n\t\t// works (one repo, several, or an org), so this refuses only the genuinely unscoped read; the scoped\n\t\t// \"assigned to anyone over these repos\" request is served by `searchIssuesPage`.\n\t\tif ((repos == null || repos.length === 0) && options?.includeAllAssignees) {\n\t\t\tthrow new IntegrationReadUnavailableError(\n\t\t\t\tthis.name,\n\t\t\t\t'`includeAllAssignees` is not supported for account-wide issue reads; scope the read to repositories instead.',\n\t\t\t);\n\t\t}\n\n\t\treturn (await this.authenticationService.apis.github)?.searchMyIssues(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\t{\n\t\t\t\trepos: repos?.map(r => `${r.owner}/${r.name}`),\n\t\t\t\tbaseUrl: this.apiBaseUrlFor(session),\n\t\t\t\tincludeBody: true,\n\t\t\t\tincludeAllAssignees: options?.includeAllAssignees,\n\t\t\t\tcursor: options?.cursor,\n\t\t\t\tpageSize: options?.pageSize,\n\t\t\t\tsort: options?.sort,\n\t\t\t\tcategories: options?.filters?.length\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tauthored: options.filters.includes(IssueFilter.Author),\n\t\t\t\t\t\t\tassigned: options.filters.includes(IssueFilter.Assignee),\n\t\t\t\t\t\t\tmentioned: options.filters.includes(IssueFilter.Mention),\n\t\t\t\t\t\t}\n\t\t\t\t\t: undefined,\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\t/**\n\t * Filtered pull-request search over a repository/organization or explicit current-user relationship scope. The\n\t * API client owns criteria sanitizing, facet unioning, ordering, and the composite cursor that carries GitHub's\n\t * result-ceiling signal across pages.\n\t */\n\tprotected override async searchProviderPullRequestsPage(\n\t\tsession: ProviderAuthenticationSession,\n\t\toptions: {\n\t\t\trepos?: ProviderRepoInput[];\n\t\t\torg?: string;\n\t\t\tcriteria?: PullRequestSearchCriteria;\n\t\t\tcursor?: string;\n\t\t\tpageSize?: number;\n\t\t\tsummary?: boolean;\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<ProviderPullRequestSearchPage | undefined> {\n\t\treturn (await this.authenticationService.apis.github)?.searchPullRequestsPage(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\t{\n\t\t\t\trepos: options.repos?.map(r => `${r.namespace}/${r.name}`),\n\t\t\t\torg: options.org,\n\t\t\t\tcriteria: options.criteria,\n\t\t\t\tbaseUrl: this.apiBaseUrlFor(session),\n\t\t\t\tcursor: options.cursor,\n\t\t\t\tpageSize: options.pageSize,\n\t\t\t\tsummary: options.summary,\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\t/**\n\t * The filtered issue search: one GraphQL request per page, no forced relationship to the current user, and no\n\t * route through the SDK's repo-scoped read (whose over-limit recovery walk can spend up to 128 requests).\n\t *\n\t * The criteria → qualifier translation and the ordering guarantee live in the API client\n\t * (`GitHubApi.searchIssuesPage`), which is also where user input is sanitized so it can't inject a qualifier.\n\t */\n\tprotected override async searchProviderIssuesPage(\n\t\tsession: ProviderAuthenticationSession,\n\t\toptions: {\n\t\t\trepos?: ProviderRepoInput[];\n\t\t\torg?: string;\n\t\t\tcriteria?: IssueSearchCriteria;\n\t\t\tcursor?: string;\n\t\t\tpageSize?: number;\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<ProviderIssueSearchPage | undefined> {\n\t\treturn (await this.authenticationService.apis.github)?.searchIssuesPage(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\t{\n\t\t\t\t// `namespace` is the owner for GitHub, which is how a `repo:` qualifier names a repository.\n\t\t\t\trepos: options.repos?.map(r => `${r.namespace}/${r.name}`),\n\t\t\t\torg: options.org,\n\t\t\t\tcriteria: options.criteria,\n\t\t\t\tbaseUrl: this.apiBaseUrlFor(session),\n\t\t\t\tincludeBody: true,\n\t\t\t\tcursor: options.cursor,\n\t\t\t\tpageSize: options.pageSize,\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\t/**\n\t * Counts several scopes in ONE request. GitHub's `search` reports `issueCount` on a zero-node selection, so a\n\t * count preview costs no issue transfer — measured, 30 aliased counts are a single rate-limit point.\n\t */\n\tprotected override async countProviderIssues(\n\t\tsession: ProviderAuthenticationSession,\n\t\tscopes: readonly { repos?: ProviderRepoInput[]; org?: string; criteria?: IssueSearchCriteria }[],\n\t\tcancellation?: AbortSignal,\n\t): Promise<(number | undefined)[] | undefined> {\n\t\treturn (await this.authenticationService.apis.github)?.countIssues(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\tscopes.map(s => ({\n\t\t\t\trepos: s.repos?.map(r => `${r.namespace}/${r.name}`),\n\t\t\t\torg: s.org,\n\t\t\t\tcriteria: s.criteria,\n\t\t\t})),\n\t\t\t{ baseUrl: this.apiBaseUrlFor(session) },\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\t/**\n\t * Resolves several issues by `(owner, repo, number)` in ONE request, by aliasing the point read rather than a\n\t * search — see {@link GitHubApi.getIssuesBatch} for why that distinction is the whole design.\n\t */\n\tprotected override async getProviderIssuesBatch(\n\t\tsession: ProviderAuthenticationSession,\n\t\tcoordinates: readonly { owner: string; repo: string; number: number }[],\n\t\tcancellation?: AbortSignal,\n\t): Promise<(IssueShape | undefined)[] | undefined> {\n\t\treturn (await this.authenticationService.apis.github)?.getIssuesBatch(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\tcoordinates,\n\t\t\t{ baseUrl: this.apiBaseUrlFor(session), includeBody: true },\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\t/**\n\t * Counts several pull-request scopes in ONE request. Like {@link countProviderIssues}, GitHub's `search`\n\t * reports `issueCount` on a zero-node selection, so a count preview costs no pull-request transfer.\n\t */\n\tprotected override async countProviderPullRequests(\n\t\tsession: ProviderAuthenticationSession,\n\t\tscopes: readonly { repos?: ProviderRepoInput[]; org?: string; criteria?: PullRequestSearchCriteria }[],\n\t\tcancellation?: AbortSignal,\n\t): Promise<ProviderPullRequestCount[] | undefined> {\n\t\tconst counts = await (\n\t\t\tawait this.authenticationService.apis.github\n\t\t)?.countPullRequests(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\tscopes.map(s => ({\n\t\t\t\trepos: s.repos?.map(r => `${r.namespace}/${r.name}`),\n\t\t\t\torg: s.org,\n\t\t\t\tcriteria: s.criteria,\n\t\t\t})),\n\t\t\t{ baseUrl: this.apiBaseUrlFor(session) },\n\t\t\tcancellation,\n\t\t);\n\t\t// `issueCount` is the search's own total, never a floor, so no slot is a lower bound.\n\t\treturn counts?.map(count => ({ count: count }));\n\t}\n\n\tprotected override async searchProviderPullRequests(\n\t\tsession: ProviderAuthenticationSession,\n\t\tsearchQuery: string,\n\t\trepos?: GitHubRepositoryDescriptor[],\n\t\tcancellation?: AbortSignal,\n\t\toptions?: SearchPullRequestsOptions,\n\t): Promise<PullRequest[] | undefined> {\n\t\treturn (await this.authenticationService.apis.github)?.searchPullRequests(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\t{\n\t\t\t\tsearch: searchQuery,\n\t\t\t\trepos: repos?.map(r => `${r.owner}/${r.name}`),\n\t\t\t\tbaseUrl: this.apiBaseUrlFor(session),\n\t\t\t\t...options,\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\t/**\n\t * Stack membership for every stacked pull request in the repository, keyed by pull request number.\n\t *\n\t * List surfaces get their pull requests from the shared providers API, whose type carries no stack\n\t * membership, so the `stack`/`stackEntry` fields selected on the native per-pull-request reads never\n\t * reach them. This fills that gap in a single request for the whole repository, rather than a\n\t * per-pull-request enrichment that would scale with the list.\n\t *\n\t * `undefined` means unavailable (not enrolled in the preview, or not connected) as distinct from an\n\t * empty map, which means the repository genuinely has no stacks.\n\t */\n\toverride async getStacksByPullRequestNumber(\n\t\towner: string,\n\t\trepo: string,\n\t\tcancellation?: AbortSignal,\n\t): Promise<Map<number, PullRequestStackInfo> | undefined> {\n\t\t// The shared read path — it refreshes an expired session before use, which a bare `getSession()`\n\t\t// does not (it returns the cached session verbatim once one exists, expired or not).\n\t\tconst session = await this.resolveReadSession(undefined, undefined);\n\t\tif (session == null) return undefined;\n\n\t\tconst stacks = await (\n\t\t\tawait this.authenticationService.apis.github\n\t\t)?.getRepositoryStacks(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\towner,\n\t\t\trepo,\n\t\t\t{\n\t\t\t\tbaseUrl: this.apiBaseUrlFor(session),\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t\tif (stacks == null) return undefined;\n\n\t\tconst byNumber = new Map<number, PullRequestStackInfo>();\n\t\tfor (const stack of stacks) {\n\t\t\t// Defensive: this is a public-preview payload reaching us through an unvalidated cast, and a\n\t\t\t// malformed entry must cost its own stack's badges, not the whole panel.\n\t\t\tconst members = stack?.pull_requests;\n\t\t\tconst baseRef = stack?.base?.ref;\n\t\t\tif (members == null || baseRef == null) continue;\n\n\t\t\t// `pull_requests` is ordered bottom to top, and `position` is 1-based from the bottom.\n\t\t\tmembers.forEach((pr, i) => {\n\t\t\t\tbyNumber.set(pr.number, {\n\t\t\t\t\tid: stack.id,\n\t\t\t\t\tnumber: stack.number,\n\t\t\t\t\tsize: members.length,\n\t\t\t\t\tposition: i + 1,\n\t\t\t\t\tbaseRef: baseRef,\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\n\t\treturn byNumber;\n\t}\n\n\tprotected override async mergeProviderPullRequest(\n\t\tsession: ProviderAuthenticationSession,\n\t\tpr: PullRequest,\n\t\toptions?: {\n\t\t\tmergeMethod?: PullRequestMergeMethod;\n\t\t},\n\t\tcancellation?: AbortSignal,\n\t): Promise<boolean> {\n\t\tconst id = pr.nodeId;\n\t\tconst headRefSha = pr.refs?.head?.sha;\n\t\tif (id == null || headRefSha == null) return false;\n\n\t\tconst api = await this.authenticationService.apis.github;\n\n\t\t// GitHub rejects stacked pull requests on the legacy merge mutation, so they take the\n\t\t// asynchronous merge instead — which also lands every layer below this one.\n\t\tif (pr.stack != null) {\n\t\t\treturn (\n\t\t\t\t(await api?.mergeStackedPullRequest(\n\t\t\t\t\tthis,\n\t\t\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\t\t\tpr.repository.owner,\n\t\t\t\t\tpr.repository.repo,\n\t\t\t\t\tNumber(pr.id),\n\t\t\t\t\theadRefSha,\n\t\t\t\t\t{\n\t\t\t\t\t\tmergeMethod: options?.mergeMethod,\n\t\t\t\t\t\tbaseUrl: this.apiBaseUrlFor(session),\n\t\t\t\t\t},\n\t\t\t\t\tcancellation,\n\t\t\t\t)) ?? false\n\t\t\t);\n\t\t}\n\n\t\treturn (\n\t\t\tapi?.mergePullRequest(\n\t\t\t\tthis,\n\t\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\t\tid,\n\t\t\t\theadRefSha,\n\t\t\t\t{\n\t\t\t\t\tmergeMethod: options?.mergeMethod,\n\t\t\t\t\tbaseUrl: this.apiBaseUrlFor(session),\n\t\t\t\t},\n\t\t\t\tcancellation,\n\t\t\t) ?? false\n\t\t);\n\t}\n\n\tprotected override async getProviderCurrentAccount(\n\t\tsession: ProviderAuthenticationSession,\n\t\toptions?: { avatarSize?: number },\n\t): Promise<Account | undefined> {\n\t\treturn (await this.authenticationService.apis.github)?.getCurrentAccount(\n\t\t\tthis,\n\t\t\ttoTokenWithInfo(this.id, session),\n\t\t\t{\n\t\t\t\t...options,\n\t\t\t\tbaseUrl: this.apiBaseUrlFor(session),\n\t\t\t},\n\t\t);\n\t}\n\n\tprotected override getProviderPullRequestIdentityFromMaybeUrl(search: string): PullRequestUrlIdentity | undefined {\n\t\treturn getGitHubPullRequestIdentityFromMaybeUrl(search, this.id);\n\t}\n}\n\nexport class GitHubIntegration extends GitHubIntegrationBase<GitCloudHostIntegrationId.GitHub> {\n\treadonly authProvider = authProvider;\n\treadonly id = GitCloudHostIntegrationId.GitHub;\n\tprotected readonly key = this.id;\n\treadonly name: string = 'GitHub';\n\tget domain(): string {\n\t\treturn metadata.domain;\n\t}\n\n\tprotected override apiBaseUrlFor(_session: ProviderAuthenticationSession): string | undefined {\n\t\t// Undefined on purpose, NOT 'https://api.github.com'. `@gitkraken/provider-apis` treats this value as an\n\t\t// *enterprise* base and derives both endpoints from it by appending GitHub Enterprise's paths:\n\t\t// `getRESTBaseUrl` appends `/api/v3` and `getGraphQLEndpoint` appends `/api/graphql` (githubHelpers.ts).\n\t\t// Handing it the cloud host therefore built `https://api.github.com/api/graphql`, which GitHub answers\n\t\t// 404 — every cloud GraphQL read (orgs, repos, PR/issue search) failed as `not-found`. Omitting it is\n\t\t// what selects the cloud endpoints (`GITHUB_API_URL` / `GITHUB_GRAPHQL_API_URL`), so cloud must pass\n\t\t// nothing and only GHE passes its instance base.\n\t\treturn undefined;\n\t}\n\n\toverride access(): Promise<boolean> {\n\t\t// Always allow GitHub cloud integration access\n\t\treturn Promise.resolve(true);\n\t}\n\n\t// This is a special case for GitHub because we use VSCode's GitHub session, and it can be disconnected\n\t// outside of the extension.\n\toverride async refresh(): Promise<void> {\n\t\tconst authProvider = await this.authenticationService.get(this.authProvider.id);\n\t\tconst session = await authProvider.getSession(this.authProviderDescriptor);\n\t\tif (session == null && this.maybeConnected) {\n\t\t\tvoid this.disconnect({ silent: true });\n\t\t} else {\n\t\t\tif (session?.accessToken !== this._session?.accessToken) {\n\t\t\t\tthis._session = undefined;\n\t\t\t}\n\t\t\tsuper.refresh();\n\t\t}\n\t}\n}\n\nexport class GitHubEnterpriseIntegration extends GitHubIntegrationBase<GitSelfManagedHostIntegrationId.CloudGitHubEnterprise> {\n\treadonly authProvider = cloudEnterpriseAuthProvider;\n\treadonly id = GitSelfManagedHostIntegrationId.CloudGitHubEnterprise;\n\tprotected readonly key;\n\treadonly name = 'GitHub Enterprise';\n\tget domain(): string {\n\t\treturn this._domain;\n\t}\n\n\tprotected override apiBaseUrlFor(session: ProviderAuthenticationSession): string {\n\t\treturn this.getSelfManagedApiBaseUrl(session);\n\t}\n\n\tconstructor(\n\t\tctx: IntegrationServiceContext,\n\t\tauthenticationService: IntegrationAuthenticationService,\n\t\tgetProvidersApi: () => Promise<ProvidersApi>,\n\t\tdidChangeConnection: Emitter<IntegrationConnectionChangeEvent>,\n\t\tprivate readonly _domain: string,\n\t) {\n\t\tsuper(ctx, authenticationService, getProvidersApi, didChangeConnection);\n\t\tthis.key = `${this.id}:${this.domain}` as const;\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -9,11 +9,11 @@ import { RepositoryMetadata } from "../../../git/models/repositoryMetadata.js";
|
|
|
9
9
|
import { PullRequestUrlIdentity } from "../../../git/utils/pullRequest.utils.js";
|
|
10
10
|
import { ProviderAuthenticationSession } from "../authentication/models.js";
|
|
11
11
|
import { GitCloudHostIntegrationId, GitSelfManagedHostIntegrationId } from "../constants.js";
|
|
12
|
+
import { ProviderOrganization } from "../results.js";
|
|
12
13
|
import { ProvidersApi } from "./providersApi.js";
|
|
13
14
|
import { AccountWideIssuesResult, SearchMyIssuesOptions } from "../models/issueReads.js";
|
|
14
15
|
import { GitHostIntegration, SearchMyPullRequestsOptions, SearchPullRequestsOptions } from "../models/gitHostIntegration.js";
|
|
15
16
|
import "../models/integration.js";
|
|
16
|
-
import { ProviderOrganization } from "../results.js";
|
|
17
17
|
import { ProviderApiPagedResult, ProviderHierarchyResult, ProviderPullRequest, ProviderRepository } from "./models.js";
|
|
18
18
|
import { IntegrationConnectionChangeEvent } from "../integrationService.js";
|
|
19
19
|
import { IntegrationAuthenticationService } from "../authentication/integrationAuthenticationService.js";
|
|
@@ -32,7 +32,9 @@ type GitLabPullRequestAssociation = 'assigned' | 'authored' | 'reviewRequested';
|
|
|
32
32
|
export declare const gitLabAssociationForFilter: Record<PullRequestFilter, GitLabPullRequestAssociation | undefined>;
|
|
33
33
|
export type GitLabRepositoryDescriptor = RepositoryDescriptor;
|
|
34
34
|
declare abstract class GitLabIntegrationBase<ID extends GitLabIntegrationIds> extends GitHostIntegration<ID, GitLabRepositoryDescriptor> {
|
|
35
|
-
protected abstract
|
|
35
|
+
protected abstract apiBaseUrlFor(session: ProviderAuthenticationSession): string;
|
|
36
|
+
/** The installation base the PAT-based reads take on self-hosted GitLab; gitlab.com passes none. */
|
|
37
|
+
protected enterpriseBaseUrlFor(session: ProviderAuthenticationSession): string | undefined;
|
|
36
38
|
/** Self-hosted GitLab uses PAT semantics and a domain-based API base; gitlab.com does not. */
|
|
37
39
|
protected get isEnterprise(): boolean;
|
|
38
40
|
protected getProviderAccountForCommit(session: ProviderAuthenticationSession, repo: GitLabRepositoryDescriptor, rev: string, options?: {
|
|
@@ -115,7 +117,7 @@ export declare class GitLabIntegration extends GitLabIntegrationBase<GitCloudHos
|
|
|
115
117
|
protected readonly key = GitCloudHostIntegrationId.GitLab;
|
|
116
118
|
readonly name: string;
|
|
117
119
|
get domain(): string;
|
|
118
|
-
protected
|
|
120
|
+
protected apiBaseUrlFor(_session: ProviderAuthenticationSession): string;
|
|
119
121
|
access(): Promise<boolean>;
|
|
120
122
|
}
|
|
121
123
|
export declare class GitLabSelfHostedIntegration extends GitLabIntegrationBase<GitSelfManagedHostIntegrationId.CloudGitLabSelfHosted> {
|
|
@@ -125,7 +127,7 @@ export declare class GitLabSelfHostedIntegration extends GitLabIntegrationBase<G
|
|
|
125
127
|
protected readonly key: `cloud-gitlab-self-hosted:${string}`;
|
|
126
128
|
readonly name = "GitLab Self-Hosted";
|
|
127
129
|
get domain(): string;
|
|
128
|
-
protected
|
|
130
|
+
protected apiBaseUrlFor(session: ProviderAuthenticationSession): string;
|
|
129
131
|
constructor(ctx: IntegrationServiceContext, authenticationService: IntegrationAuthenticationService, getProvidersApi: () => Promise<ProvidersApi>, didChangeConnection: Emitter<IntegrationConnectionChangeEvent>, _domain: string);
|
|
130
132
|
}
|
|
131
133
|
//#endregion
|
|
@@ -3,12 +3,12 @@ import { CancellationError } from "../../../utils/cancellation.js";
|
|
|
3
3
|
import { batch } from "../../../utils/promise.js";
|
|
4
4
|
import "../../../git/models/pullRequest.js";
|
|
5
5
|
import { IntegrationReadUnavailableError } from "../errors.js";
|
|
6
|
-
import { toCollectionScopeFailure } from "../collectionMetadata.js";
|
|
7
6
|
import "../constants.js";
|
|
7
|
+
import { toCollectionScopeFailure } from "../collectionMetadata.js";
|
|
8
8
|
import { toTokenWithInfo } from "../authentication/models.js";
|
|
9
9
|
import "../providerFilters.js";
|
|
10
|
-
import { ProviderPullRequestReviewState, getProviderPullRequestIdentity, providersMetadata, toIssueShape, toProviderPullRequestStates } from "./models.js";
|
|
11
10
|
import { collectProviderPagedResult, mergeCollectionMetadata } from "./utils/providerPaging.js";
|
|
11
|
+
import { ProviderPullRequestReviewState, getProviderPullRequestIdentity, providersMetadata, toIssueShape, toProviderPullRequestStates } from "./models.js";
|
|
12
12
|
import { getGitLabPullRequestIdentityFromMaybeUrl, matchesGitLabOrgNamespace } from "./gitlab/gitlab.utils.js";
|
|
13
13
|
import { fromGitLabMergeRequestProvidersApi } from "./gitlab/models.js";
|
|
14
14
|
import { GitHostIntegration } from "../models/gitHostIntegration.js";
|
|
@@ -56,6 +56,10 @@ function parseGitLabPullRequestFacetCursor(cursor) {
|
|
|
56
56
|
/** How many SSH signing-key lookups (account resolve + keys fetch) to run concurrently, to avoid a request burst. */
|
|
57
57
|
const sshSigningKeyResolveBatchSize = 10;
|
|
58
58
|
var GitLabIntegrationBase = class extends GitHostIntegration {
|
|
59
|
+
/** The installation base the PAT-based reads take on self-hosted GitLab; gitlab.com passes none. */
|
|
60
|
+
enterpriseBaseUrlFor(session) {
|
|
61
|
+
return this.isEnterprise ? this.getSelfManagedApiBaseUrl(session) : void 0;
|
|
62
|
+
}
|
|
59
63
|
/** Self-hosted GitLab uses PAT semantics and a domain-based API base; gitlab.com does not. */
|
|
60
64
|
get isEnterprise() {
|
|
61
65
|
return this.id === "cloud-gitlab-self-hosted";
|
|
@@ -63,13 +67,13 @@ var GitLabIntegrationBase = class extends GitHostIntegration {
|
|
|
63
67
|
async getProviderAccountForCommit(session, repo, rev, options) {
|
|
64
68
|
return (await this.authenticationService.apis.gitlab)?.getAccountForCommit(this, toTokenWithInfo(this.id, session), repo.owner, repo.name, rev, {
|
|
65
69
|
...options,
|
|
66
|
-
baseUrl: this.
|
|
70
|
+
baseUrl: this.apiBaseUrlFor(session)
|
|
67
71
|
});
|
|
68
72
|
}
|
|
69
73
|
async getProviderAccountForEmail(session, repo, email, options) {
|
|
70
74
|
return (await this.authenticationService.apis.gitlab)?.getAccountForEmail(this, toTokenWithInfo(this.id, session), repo.owner, repo.name, email, {
|
|
71
75
|
...options,
|
|
72
|
-
baseUrl: this.
|
|
76
|
+
baseUrl: this.apiBaseUrlFor(session)
|
|
73
77
|
});
|
|
74
78
|
}
|
|
75
79
|
async getProviderSshSigningKeysForEmails(session, repo, emails) {
|
|
@@ -80,29 +84,29 @@ var GitLabIntegrationBase = class extends GitHostIntegration {
|
|
|
80
84
|
await batch(emails, sshSigningKeyResolveBatchSize, async (email) => {
|
|
81
85
|
const account = await this.getProviderAccountForEmail(session, repo, email);
|
|
82
86
|
if (account?.id == null) return;
|
|
83
|
-
const keys = await api.getUserSigningKeys(this, token, account.id, { baseUrl: this.
|
|
87
|
+
const keys = await api.getUserSigningKeys(this, token, account.id, { baseUrl: this.apiBaseUrlFor(session) });
|
|
84
88
|
result.set(email.toLowerCase(), keys.map((k) => k.key));
|
|
85
89
|
});
|
|
86
90
|
return result;
|
|
87
91
|
}
|
|
88
92
|
async getProviderDefaultBranch(session, repo) {
|
|
89
|
-
return (await this.authenticationService.apis.gitlab)?.getDefaultBranch(this, toTokenWithInfo(this.id, session), repo.owner, repo.name, { baseUrl: this.
|
|
93
|
+
return (await this.authenticationService.apis.gitlab)?.getDefaultBranch(this, toTokenWithInfo(this.id, session), repo.owner, repo.name, { baseUrl: this.apiBaseUrlFor(session) });
|
|
90
94
|
}
|
|
91
95
|
async getProviderLinkedIssueOrPullRequest(session, repo, { id }) {
|
|
92
|
-
return (await this.authenticationService.apis.gitlab)?.getIssueOrPullRequest(this, toTokenWithInfo(this.id, session), repo.owner, repo.name, Number(id), { baseUrl: this.
|
|
96
|
+
return (await this.authenticationService.apis.gitlab)?.getIssueOrPullRequest(this, toTokenWithInfo(this.id, session), repo.owner, repo.name, Number(id), { baseUrl: this.apiBaseUrlFor(session) });
|
|
93
97
|
}
|
|
94
98
|
async getProviderIssue(session, repo, id) {
|
|
95
99
|
const api = await this.authenticationService.apis.gitlab;
|
|
96
100
|
const providerApi = await this.getProvidersApi();
|
|
97
101
|
if (!api || !repo || !id) return;
|
|
98
|
-
if (!await api.getProjectId(this, toTokenWithInfo(this.id, session), repo.owner, repo.name, this.
|
|
102
|
+
if (!await api.getProjectId(this, toTokenWithInfo(this.id, session), repo.owner, repo.name, this.apiBaseUrlFor(session), void 0)) return;
|
|
99
103
|
const apiResult = await providerApi.getIssue(toTokenWithInfo(this.id, session), {
|
|
100
104
|
namespace: repo.owner,
|
|
101
105
|
name: repo.name,
|
|
102
106
|
number: id
|
|
103
107
|
}, {
|
|
104
108
|
isPAT: this.isEnterprise,
|
|
105
|
-
baseUrl: this.
|
|
109
|
+
baseUrl: this.enterpriseBaseUrlFor(session)
|
|
106
110
|
});
|
|
107
111
|
const issue = apiResult != null ? toIssueShape(apiResult, this) : void 0;
|
|
108
112
|
return issue != null ? {
|
|
@@ -119,14 +123,14 @@ var GitLabIntegrationBase = class extends GitHostIntegration {
|
|
|
119
123
|
return (await this.authenticationService.apis.gitlab)?.getPullRequestForBranch(this, toTokenWithInfo(this.id, session), repo.owner, repo.name, branch, {
|
|
120
124
|
...opts,
|
|
121
125
|
include: include?.map((s) => toGitLabMergeRequestState(s)),
|
|
122
|
-
baseUrl: this.
|
|
126
|
+
baseUrl: this.apiBaseUrlFor(session)
|
|
123
127
|
});
|
|
124
128
|
}
|
|
125
129
|
async getProviderPullRequestForCommit(session, repo, rev) {
|
|
126
|
-
return (await this.authenticationService.apis.gitlab)?.getPullRequestForCommit(this, toTokenWithInfo(this.id, session), repo.owner, repo.name, rev, { baseUrl: this.
|
|
130
|
+
return (await this.authenticationService.apis.gitlab)?.getPullRequestForCommit(this, toTokenWithInfo(this.id, session), repo.owner, repo.name, rev, { baseUrl: this.apiBaseUrlFor(session) });
|
|
127
131
|
}
|
|
128
132
|
async getProviderPullRequest(session, resource, id) {
|
|
129
|
-
return (await this.authenticationService.apis.gitlab)?.getPullRequest(this, toTokenWithInfo(this.id, session), resource.owner, resource.name, parseInt(id, 10), { baseUrl: this.
|
|
133
|
+
return (await this.authenticationService.apis.gitlab)?.getPullRequest(this, toTokenWithInfo(this.id, session), resource.owner, resource.name, parseInt(id, 10), { baseUrl: this.apiBaseUrlFor(session) });
|
|
130
134
|
}
|
|
131
135
|
async getRepoInfo(repo) {
|
|
132
136
|
const api = await this.getProvidersApi();
|
|
@@ -134,16 +138,16 @@ var GitLabIntegrationBase = class extends GitHostIntegration {
|
|
|
134
138
|
if (session == null) return void 0;
|
|
135
139
|
return api.getRepo(toTokenWithInfo(this.id, session), repo.owner, repo.name, repo.project, {
|
|
136
140
|
isPAT: this.isEnterprise,
|
|
137
|
-
baseUrl: this.
|
|
141
|
+
baseUrl: this.enterpriseBaseUrlFor(session)
|
|
138
142
|
});
|
|
139
143
|
}
|
|
140
144
|
async getProviderRepositoryMetadata(session, repo, cancellation) {
|
|
141
|
-
return (await this.authenticationService.apis.gitlab)?.getRepositoryMetadata(this, toTokenWithInfo(this.id, session), repo.owner, repo.name, { baseUrl: this.
|
|
145
|
+
return (await this.authenticationService.apis.gitlab)?.getRepositoryMetadata(this, toTokenWithInfo(this.id, session), repo.owner, repo.name, { baseUrl: this.apiBaseUrlFor(session) }, cancellation);
|
|
142
146
|
}
|
|
143
147
|
async getProviderOrganizationsForUser(session) {
|
|
144
148
|
const result = await (await this.getProvidersApi()).getGitlabGroupsForCurrentUser(toTokenWithInfo(this.id, session), {
|
|
145
149
|
isPAT: this.isEnterprise,
|
|
146
|
-
baseUrl: this.
|
|
150
|
+
baseUrl: this.enterpriseBaseUrlFor(session)
|
|
147
151
|
});
|
|
148
152
|
return {
|
|
149
153
|
values: result.values.map((g) => ({
|
|
@@ -167,7 +171,7 @@ var GitLabIntegrationBase = class extends GitHostIntegration {
|
|
|
167
171
|
async getProviderRepositoriesForOrg(session, org, options) {
|
|
168
172
|
const result = await (await this.getProvidersApi()).getReposForCurrentUser(toTokenWithInfo(this.id, session), {
|
|
169
173
|
isPAT: this.isEnterprise,
|
|
170
|
-
baseUrl: this.
|
|
174
|
+
baseUrl: this.enterpriseBaseUrlFor(session),
|
|
171
175
|
cursor: options?.cursor
|
|
172
176
|
});
|
|
173
177
|
return {
|
|
@@ -178,7 +182,7 @@ var GitLabIntegrationBase = class extends GitHostIntegration {
|
|
|
178
182
|
async getProviderRepositoriesForUser(session, options) {
|
|
179
183
|
return (await this.getProvidersApi()).getReposForCurrentUser(toTokenWithInfo(this.id, session), {
|
|
180
184
|
isPAT: this.isEnterprise,
|
|
181
|
-
baseUrl: this.
|
|
185
|
+
baseUrl: this.enterpriseBaseUrlFor(session),
|
|
182
186
|
cursor: options?.cursor
|
|
183
187
|
});
|
|
184
188
|
}
|
|
@@ -188,7 +192,7 @@ var GitLabIntegrationBase = class extends GitHostIntegration {
|
|
|
188
192
|
if (!username) return Promise.resolve([]);
|
|
189
193
|
const apiResult = await api.getPullRequestsForUser(toTokenWithInfo(this.id, session), username, {
|
|
190
194
|
isPAT: this.isEnterprise,
|
|
191
|
-
baseUrl: this.
|
|
195
|
+
baseUrl: this.enterpriseBaseUrlFor(session),
|
|
192
196
|
states: toProviderPullRequestStates(options?.state)
|
|
193
197
|
});
|
|
194
198
|
if (apiResult == null) return Promise.resolve([]);
|
|
@@ -227,7 +231,7 @@ var GitLabIntegrationBase = class extends GitHostIntegration {
|
|
|
227
231
|
association,
|
|
228
232
|
result: await api.getGitLabPullRequestsForUserAssociation(tokenWithInfo, username, association, {
|
|
229
233
|
isPAT: this.isEnterprise,
|
|
230
|
-
baseUrl: this.
|
|
234
|
+
baseUrl: this.enterpriseBaseUrlFor(session),
|
|
231
235
|
states: toProviderPullRequestStates(options?.state),
|
|
232
236
|
cursor: cursors[association]
|
|
233
237
|
})
|
|
@@ -286,10 +290,10 @@ var GitLabIntegrationBase = class extends GitHostIntegration {
|
|
|
286
290
|
const api = await this.authenticationService.apis.gitlab;
|
|
287
291
|
const providerApi = await this.getProvidersApi();
|
|
288
292
|
if (!api || !repos) return;
|
|
289
|
-
const repoInput = (await Promise.allSettled(repos.map((r) => api.getProjectId(this, toTokenWithInfo(this.id, session), r.owner, r.name, this.
|
|
293
|
+
const repoInput = (await Promise.allSettled(repos.map((r) => api.getProjectId(this, toTokenWithInfo(this.id, session), r.owner, r.name, this.apiBaseUrlFor(session), void 0)) ?? [])).map((result) => result.status === "fulfilled" ? result.value : void 0).filter((r) => r != null);
|
|
290
294
|
return (await providerApi.getIssuesForRepos(toTokenWithInfo(this.id, session), repoInput, {
|
|
291
295
|
isPAT: this.isEnterprise,
|
|
292
|
-
baseUrl: this.
|
|
296
|
+
baseUrl: this.enterpriseBaseUrlFor(session)
|
|
293
297
|
})).values.map((issue) => toIssueShape(issue, this)).filter((result) => result != null);
|
|
294
298
|
}
|
|
295
299
|
/**
|
|
@@ -314,7 +318,7 @@ var GitLabIntegrationBase = class extends GitHostIntegration {
|
|
|
314
318
|
const username = options?.includeAllAssignees ? void 0 : (await this.getProviderCurrentAccount(session))?.username;
|
|
315
319
|
if (!options?.includeAllAssignees && username == null) return void 0;
|
|
316
320
|
if (cancellation?.aborted) throw new CancellationError();
|
|
317
|
-
const baseUrl = this.
|
|
321
|
+
const baseUrl = this.enterpriseBaseUrlFor(session);
|
|
318
322
|
const maxPages = 20;
|
|
319
323
|
const issuesByUrl = /* @__PURE__ */ new Map();
|
|
320
324
|
let truncated = false;
|
|
@@ -364,7 +368,7 @@ var GitLabIntegrationBase = class extends GitHostIntegration {
|
|
|
364
368
|
return api.searchPullRequests(this, toTokenWithInfo(this.id, session), {
|
|
365
369
|
search: searchQuery,
|
|
366
370
|
repos: repos?.map((r) => `${r.owner}/${r.name}`),
|
|
367
|
-
baseUrl: this.
|
|
371
|
+
baseUrl: this.apiBaseUrlFor(session),
|
|
368
372
|
include: options?.include
|
|
369
373
|
}, cancellation);
|
|
370
374
|
}
|
|
@@ -375,7 +379,7 @@ var GitLabIntegrationBase = class extends GitHostIntegration {
|
|
|
375
379
|
return await api.mergePullRequest(toTokenWithInfo(this.id, session), pr, {
|
|
376
380
|
...options,
|
|
377
381
|
isPAT: this.isEnterprise,
|
|
378
|
-
baseUrl: this.
|
|
382
|
+
baseUrl: this.enterpriseBaseUrlFor(session)
|
|
379
383
|
});
|
|
380
384
|
} catch (ex) {
|
|
381
385
|
this.showMergeErrorMessage(ex);
|
|
@@ -391,7 +395,7 @@ var GitLabIntegrationBase = class extends GitHostIntegration {
|
|
|
391
395
|
async getProviderCurrentAccount(session) {
|
|
392
396
|
const currentUser = await (await this.getProvidersApi()).getCurrentUser(toTokenWithInfo(this.id, session), {
|
|
393
397
|
isPAT: this.isEnterprise,
|
|
394
|
-
baseUrl: this.
|
|
398
|
+
baseUrl: this.enterpriseBaseUrlFor(session)
|
|
395
399
|
});
|
|
396
400
|
if (currentUser == null) return void 0;
|
|
397
401
|
return {
|
|
@@ -420,7 +424,7 @@ var GitLabIntegration = class extends GitLabIntegrationBase {
|
|
|
420
424
|
get domain() {
|
|
421
425
|
return metadata.domain;
|
|
422
426
|
}
|
|
423
|
-
|
|
427
|
+
apiBaseUrlFor(_session) {
|
|
424
428
|
return "https://gitlab.com/api";
|
|
425
429
|
}
|
|
426
430
|
access() {
|
|
@@ -436,8 +440,8 @@ var GitLabSelfHostedIntegration = class extends GitLabIntegrationBase {
|
|
|
436
440
|
get domain() {
|
|
437
441
|
return this._domain;
|
|
438
442
|
}
|
|
439
|
-
|
|
440
|
-
return
|
|
443
|
+
apiBaseUrlFor(session) {
|
|
444
|
+
return `${this.getSelfManagedApiBaseUrl(session)}/api`;
|
|
441
445
|
}
|
|
442
446
|
constructor(ctx, authenticationService, getProvidersApi, didChangeConnection, _domain) {
|
|
443
447
|
super(ctx, authenticationService, getProvidersApi, didChangeConnection);
|