@gitkraken/core-gitlens 0.5.113 → 0.5.115
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 +42 -1
- package/dist/git/cache.d.ts +4 -0
- package/dist/git/cache.d.ts.map +1 -1
- package/dist/git/cache.js +33 -0
- package/dist/git/cache.js.map +1 -1
- package/dist/git/context.d.ts +10 -0
- package/dist/git/context.d.ts.map +1 -1
- package/dist/git/context.js.map +1 -1
- package/dist/git/errors.d.ts +6 -3
- package/dist/git/errors.d.ts.map +1 -1
- package/dist/git/errors.js +9 -1
- package/dist/git/errors.js.map +1 -1
- package/dist/git/features.d.ts +1 -1
- package/dist/git/features.d.ts.map +1 -1
- package/dist/git/features.js +38 -0
- package/dist/git/features.js.map +1 -1
- package/dist/git/gitHealth.d.ts +153 -0
- package/dist/git/gitHealth.d.ts.map +1 -0
- package/dist/git/gitHealth.js +353 -0
- package/dist/git/gitHealth.js.map +1 -0
- package/dist/git/models/search.d.ts +6 -3
- package/dist/git/models/search.d.ts.map +1 -1
- package/dist/git/models/search.js +5 -1
- package/dist/git/models/search.js.map +1 -1
- package/dist/git/parsers/diffParser.d.ts +8 -2
- package/dist/git/parsers/diffParser.d.ts.map +1 -1
- package/dist/git/parsers/diffParser.js +27 -4
- package/dist/git/parsers/diffParser.js.map +1 -1
- package/dist/git/providers/config.d.ts +36 -3
- package/dist/git/providers/config.d.ts.map +1 -1
- package/dist/git/providers/graph.d.ts +9 -0
- package/dist/git/providers/graph.d.ts.map +1 -1
- package/dist/git/providers/maintenance.d.ts +222 -0
- package/dist/git/providers/maintenance.d.ts.map +1 -0
- package/dist/git/providers/maintenance.js +20 -0
- package/dist/git/providers/maintenance.js.map +1 -0
- package/dist/git/providers/operations.d.ts +10 -0
- package/dist/git/providers/operations.d.ts.map +1 -1
- package/dist/git/providers/pausedOperations.d.ts +3 -0
- package/dist/git/providers/pausedOperations.d.ts.map +1 -1
- package/dist/git/providers/provider.d.ts +2 -0
- package/dist/git/providers/provider.d.ts.map +1 -1
- package/dist/git/providers/tags.d.ts +3 -0
- package/dist/git/providers/tags.d.ts.map +1 -1
- package/dist/git/repositoryService.d.ts +1 -0
- package/dist/git/repositoryService.d.ts.map +1 -1
- package/dist/git/repositoryService.js.map +1 -1
- package/dist/git/run.types.d.ts +8 -0
- package/dist/git/run.types.d.ts.map +1 -1
- package/dist/git/service.js +3 -0
- package/dist/git/service.js.map +1 -1
- package/dist/git/utils/search.utils.d.ts.map +1 -1
- package/dist/git/utils/search.utils.js +112 -5
- package/dist/git/utils/search.utils.js.map +1 -1
- package/dist/git/watching/watchService.d.ts +3 -0
- package/dist/git/watching/watchService.d.ts.map +1 -1
- package/dist/git/watching/watchService.js +8 -0
- package/dist/git/watching/watchService.js.map +1 -1
- package/dist/git-cli/cliGitProvider.d.ts +11 -0
- package/dist/git-cli/cliGitProvider.d.ts.map +1 -1
- package/dist/git-cli/cliGitProvider.js +12 -0
- package/dist/git-cli/cliGitProvider.js.map +1 -1
- package/dist/git-cli/exec/git.d.ts +23 -1
- package/dist/git-cli/exec/git.d.ts.map +1 -1
- package/dist/git-cli/exec/git.js +83 -8
- package/dist/git-cli/exec/git.js.map +1 -1
- package/dist/git-cli/exec/gitQueue.d.ts +2 -0
- package/dist/git-cli/exec/gitQueue.d.ts.map +1 -1
- package/dist/git-cli/exec/gitQueue.js +19 -17
- package/dist/git-cli/exec/gitQueue.js.map +1 -1
- package/dist/git-cli/parsers/logParser.d.ts.map +1 -1
- package/dist/git-cli/parsers/logParser.js +4 -1
- package/dist/git-cli/parsers/logParser.js.map +1 -1
- package/dist/git-cli/providers/blame.d.ts.map +1 -1
- package/dist/git-cli/providers/blame.js +4 -7
- package/dist/git-cli/providers/blame.js.map +1 -1
- package/dist/git-cli/providers/branches.d.ts.map +1 -1
- package/dist/git-cli/providers/branches.js +13 -3
- package/dist/git-cli/providers/branches.js.map +1 -1
- package/dist/git-cli/providers/commits.d.ts.map +1 -1
- package/dist/git-cli/providers/commits.js +34 -3
- package/dist/git-cli/providers/commits.js.map +1 -1
- package/dist/git-cli/providers/config.d.ts +27 -0
- package/dist/git-cli/providers/config.d.ts.map +1 -1
- package/dist/git-cli/providers/config.js +31 -6
- package/dist/git-cli/providers/config.js.map +1 -1
- package/dist/git-cli/providers/graph.d.ts +8 -0
- package/dist/git-cli/providers/graph.d.ts.map +1 -1
- package/dist/git-cli/providers/graph.js +85 -6
- package/dist/git-cli/providers/graph.js.map +1 -1
- package/dist/git-cli/providers/maintenance.d.ts +306 -0
- package/dist/git-cli/providers/maintenance.d.ts.map +1 -0
- package/dist/git-cli/providers/maintenance.js +2129 -0
- package/dist/git-cli/providers/maintenance.js.map +1 -0
- package/dist/git-cli/providers/operations.d.ts +1 -0
- package/dist/git-cli/providers/operations.d.ts.map +1 -1
- package/dist/git-cli/providers/operations.js +8 -0
- package/dist/git-cli/providers/operations.js.map +1 -1
- package/dist/git-cli/providers/pausedOperations.d.ts +1 -0
- package/dist/git-cli/providers/pausedOperations.d.ts.map +1 -1
- package/dist/git-cli/providers/pausedOperations.js +1 -1
- package/dist/git-cli/providers/pausedOperations.js.map +1 -1
- package/dist/git-cli/providers/tags.d.ts +3 -0
- package/dist/git-cli/providers/tags.d.ts.map +1 -1
- package/dist/git-cli/providers/tags.js +23 -1
- package/dist/git-cli/providers/tags.js.map +1 -1
- package/dist/plus/agents/agentCapabilities.d.ts +77 -0
- package/dist/plus/agents/agentCapabilities.d.ts.map +1 -0
- package/dist/plus/agents/agentCapabilities.js +197 -0
- package/dist/plus/agents/agentCapabilities.js.map +1 -0
- package/dist/plus/agents/providers/claudeCodeTranscript.d.ts +77 -13
- package/dist/plus/agents/providers/claudeCodeTranscript.d.ts.map +1 -1
- package/dist/plus/agents/providers/claudeCodeTranscript.js +263 -55
- package/dist/plus/agents/providers/claudeCodeTranscript.js.map +1 -1
- package/dist/plus/agents/providers/{claudeCodeProvider.d.ts → gkAgentProvider.d.ts} +52 -19
- package/dist/plus/agents/providers/gkAgentProvider.d.ts.map +1 -0
- package/dist/plus/agents/providers/{claudeCodeProvider.js → gkAgentProvider.js} +935 -262
- package/dist/plus/agents/providers/gkAgentProvider.js.map +1 -0
- package/dist/plus/agents/types.d.ts +113 -35
- package/dist/plus/agents/types.d.ts.map +1 -1
- package/dist/plus/agents/types.js +7 -4
- package/dist/plus/agents/types.js.map +1 -1
- package/dist/plus/ai/models/promptTemplates.d.ts +1 -1
- package/dist/plus/ai/models/promptTemplates.d.ts.map +1 -1
- package/dist/plus/ai/prompts.d.ts +4 -0
- package/dist/plus/ai/prompts.d.ts.map +1 -1
- package/dist/plus/ai/prompts.js +59 -4
- package/dist/plus/ai/prompts.js.map +1 -1
- package/dist/plus/git-github/api/github.d.ts +44 -1
- package/dist/plus/git-github/api/github.d.ts.map +1 -1
- package/dist/plus/git-github/api/github.js +355 -62
- package/dist/plus/git-github/api/github.js.map +1 -1
- package/dist/plus/git-github/api/issueSearchQuery.d.ts +13 -0
- package/dist/plus/git-github/api/issueSearchQuery.d.ts.map +1 -1
- package/dist/plus/git-github/api/issueSearchQuery.js +41 -0
- package/dist/plus/git-github/api/issueSearchQuery.js.map +1 -1
- package/dist/plus/git-github/providers/github/blame.d.ts.map +1 -1
- package/dist/plus/git-github/providers/github/blame.js +2 -1
- package/dist/plus/git-github/providers/github/blame.js.map +1 -1
- package/dist/plus/integrations/collectionMetadata.d.ts +2 -0
- package/dist/plus/integrations/collectionMetadata.d.ts.map +1 -1
- package/dist/plus/integrations/collectionMetadata.js +17 -1
- package/dist/plus/integrations/collectionMetadata.js.map +1 -1
- package/dist/plus/integrations/context.d.ts +4 -1
- package/dist/plus/integrations/context.d.ts.map +1 -1
- package/dist/plus/integrations/index.d.ts +1 -0
- package/dist/plus/integrations/index.d.ts.map +1 -1
- package/dist/plus/integrations/integrationService.d.ts +20 -1
- package/dist/plus/integrations/integrationService.d.ts.map +1 -1
- package/dist/plus/integrations/integrationService.js +12 -4
- package/dist/plus/integrations/integrationService.js.map +1 -1
- package/dist/plus/integrations/manager.d.ts +48 -0
- package/dist/plus/integrations/manager.d.ts.map +1 -1
- package/dist/plus/integrations/models/gitHostIntegration.d.ts +53 -26
- package/dist/plus/integrations/models/gitHostIntegration.d.ts.map +1 -1
- package/dist/plus/integrations/models/gitHostIntegration.js +123 -47
- package/dist/plus/integrations/models/gitHostIntegration.js.map +1 -1
- package/dist/plus/integrations/models/integration.d.ts +10 -1
- package/dist/plus/integrations/models/integration.d.ts.map +1 -1
- package/dist/plus/integrations/models/integration.js +52 -19
- package/dist/plus/integrations/models/integration.js.map +1 -1
- package/dist/plus/integrations/models/issueCache.d.ts +16 -0
- package/dist/plus/integrations/models/issueCache.d.ts.map +1 -0
- package/dist/plus/integrations/models/issueCache.js +9 -0
- package/dist/plus/integrations/models/issueCache.js.map +1 -0
- package/dist/plus/integrations/models/issueReads.d.ts +13 -0
- package/dist/plus/integrations/models/issueReads.d.ts.map +1 -1
- package/dist/plus/integrations/models/issuesIntegration.d.ts +11 -13
- package/dist/plus/integrations/models/issuesIntegration.d.ts.map +1 -1
- package/dist/plus/integrations/models/issuesIntegration.js +15 -1
- package/dist/plus/integrations/models/issuesIntegration.js.map +1 -1
- package/dist/plus/integrations/providers/azureDevOps.d.ts +3 -5
- package/dist/plus/integrations/providers/azureDevOps.d.ts.map +1 -1
- package/dist/plus/integrations/providers/azureDevOps.js +9 -8
- package/dist/plus/integrations/providers/azureDevOps.js.map +1 -1
- package/dist/plus/integrations/providers/bitbucket-server.d.ts +3 -5
- package/dist/plus/integrations/providers/bitbucket-server.d.ts.map +1 -1
- package/dist/plus/integrations/providers/bitbucket-server.js +2 -2
- package/dist/plus/integrations/providers/bitbucket-server.js.map +1 -1
- package/dist/plus/integrations/providers/bitbucket.d.ts +3 -5
- package/dist/plus/integrations/providers/bitbucket.d.ts.map +1 -1
- package/dist/plus/integrations/providers/bitbucket.js +2 -1
- package/dist/plus/integrations/providers/bitbucket.js.map +1 -1
- package/dist/plus/integrations/providers/github.d.ts +12 -5
- package/dist/plus/integrations/providers/github.d.ts.map +1 -1
- package/dist/plus/integrations/providers/github.js +10 -3
- package/dist/plus/integrations/providers/github.js.map +1 -1
- package/dist/plus/integrations/providers/gitlab.d.ts +3 -5
- package/dist/plus/integrations/providers/gitlab.d.ts.map +1 -1
- package/dist/plus/integrations/providers/gitlab.js +2 -2
- package/dist/plus/integrations/providers/gitlab.js.map +1 -1
- package/dist/plus/integrations/providers/jira.d.ts +3 -7
- package/dist/plus/integrations/providers/jira.d.ts.map +1 -1
- package/dist/plus/integrations/providers/jira.js +35 -22
- package/dist/plus/integrations/providers/jira.js.map +1 -1
- package/dist/plus/integrations/providers/jiraIssueByKey.d.ts +7 -0
- package/dist/plus/integrations/providers/jiraIssueByKey.d.ts.map +1 -0
- package/dist/plus/integrations/providers/jiraIssueByKey.js +102 -0
- package/dist/plus/integrations/providers/jiraIssueByKey.js.map +1 -0
- package/dist/plus/integrations/providers/linear.d.ts +3 -7
- package/dist/plus/integrations/providers/linear.d.ts.map +1 -1
- package/dist/plus/integrations/providers/linear.js +23 -22
- package/dist/plus/integrations/providers/linear.js.map +1 -1
- package/dist/plus/integrations/providers/models.d.ts +3 -1
- package/dist/plus/integrations/providers/models.d.ts.map +1 -1
- package/dist/plus/integrations/providers/models.js +10 -4
- package/dist/plus/integrations/providers/models.js.map +1 -1
- package/dist/plus/integrations/providers/providerErrors.d.ts +7 -0
- package/dist/plus/integrations/providers/providerErrors.d.ts.map +1 -0
- package/dist/plus/integrations/providers/providerErrors.js +91 -0
- package/dist/plus/integrations/providers/providerErrors.js.map +1 -0
- package/dist/plus/integrations/providers/providersApi.d.ts +3 -2
- package/dist/plus/integrations/providers/providersApi.d.ts.map +1 -1
- package/dist/plus/integrations/providers/providersApi.js +18 -52
- package/dist/plus/integrations/providers/providersApi.js.map +1 -1
- package/dist/plus/integrations/providers/trello.d.ts +2 -7
- package/dist/plus/integrations/providers/trello.d.ts.map +1 -1
- package/dist/plus/integrations/providers/trello.js +3 -1
- package/dist/plus/integrations/providers/trello.js.map +1 -1
- package/dist/plus/integrations/providers/utils/providerPaging.d.ts +2 -0
- package/dist/plus/integrations/providers/utils/providerPaging.d.ts.map +1 -1
- package/dist/plus/integrations/providers/utils/providerPaging.js +12 -7
- package/dist/plus/integrations/providers/utils/providerPaging.js.map +1 -1
- package/dist/plus/integrations/reads/broaden.d.ts +47 -10
- package/dist/plus/integrations/reads/broaden.d.ts.map +1 -1
- package/dist/plus/integrations/reads/broaden.js +144 -33
- package/dist/plus/integrations/reads/broaden.js.map +1 -1
- package/dist/plus/integrations/reads/filters.d.ts +18 -0
- package/dist/plus/integrations/reads/filters.d.ts.map +1 -1
- package/dist/plus/integrations/reads/filters.js +37 -1
- package/dist/plus/integrations/reads/filters.js.map +1 -1
- package/dist/plus/integrations/reads/issueBatch.d.ts +51 -0
- package/dist/plus/integrations/reads/issueBatch.d.ts.map +1 -0
- package/dist/plus/integrations/reads/issueBatch.js +91 -0
- package/dist/plus/integrations/reads/issueBatch.js.map +1 -0
- package/dist/plus/integrations/reads/issueTracker.d.ts.map +1 -1
- package/dist/plus/integrations/reads/issueTracker.js +23 -17
- package/dist/plus/integrations/reads/issueTracker.js.map +1 -1
- package/dist/plus/integrations/reads/sweeps.d.ts.map +1 -1
- package/dist/plus/integrations/reads/sweeps.js +5 -3
- package/dist/plus/integrations/reads/sweeps.js.map +1 -1
- package/dist/plus/integrations/reads/trackerIssue.d.ts +21 -0
- package/dist/plus/integrations/reads/trackerIssue.d.ts.map +1 -0
- package/dist/plus/integrations/reads/trackerIssue.js +51 -0
- package/dist/plus/integrations/reads/trackerIssue.js.map +1 -0
- package/dist/plus/integrations/reads/warnings.d.ts +2 -15
- package/dist/plus/integrations/reads/warnings.d.ts.map +1 -1
- package/dist/plus/integrations/reads/warnings.js +19 -1
- package/dist/plus/integrations/reads/warnings.js.map +1 -1
- package/dist/plus/integrations/results.d.ts +4 -20
- package/dist/plus/integrations/results.d.ts.map +1 -1
- package/dist/plus/integrations/results.js.map +1 -1
- package/dist/utils/promise.d.ts +2 -0
- package/dist/utils/promise.d.ts.map +1 -1
- package/dist/utils/promise.js +11 -0
- package/dist/utils/promise.js.map +1 -1
- package/dist/utils/promiseCache.d.ts +19 -0
- package/dist/utils/promiseCache.d.ts.map +1 -1
- package/dist/utils/promiseCache.js +30 -0
- package/dist/utils/promiseCache.js.map +1 -1
- package/dist/utils/resourceUsage.d.ts +5 -0
- package/dist/utils/resourceUsage.d.ts.map +1 -0
- package/dist/utils/resourceUsage.js +2 -0
- package/dist/utils/resourceUsage.js.map +1 -0
- package/dist/utils/string.d.ts +12 -0
- package/dist/utils/string.d.ts.map +1 -1
- package/dist/utils/string.js +36 -1
- package/dist/utils/string.js.map +1 -1
- package/docs/integrations.md +48 -33
- package/docs/kepler-read-api-parity.md +25 -4
- package/package.json +12 -4
- package/src/git/cache.ts +36 -0
- package/src/git/context.ts +11 -0
- package/src/git/errors.ts +13 -1
- package/src/git/features.ts +51 -0
- package/src/git/gitHealth.ts +522 -0
- package/src/git/models/search.ts +19 -4
- package/src/git/parsers/diffParser.ts +27 -4
- package/src/git/providers/config.ts +42 -1
- package/src/git/providers/graph.ts +12 -0
- package/src/git/providers/maintenance.ts +224 -0
- package/src/git/providers/operations.ts +10 -0
- package/src/git/providers/pausedOperations.ts +3 -0
- package/src/git/providers/provider.ts +2 -0
- package/src/git/providers/tags.ts +1 -0
- package/src/git/repositoryService.ts +1 -0
- package/src/git/run.types.ts +8 -0
- package/src/git/service.ts +3 -0
- package/src/git/utils/search.utils.ts +129 -5
- package/src/git/watching/watchService.ts +10 -0
- package/src/git-cli/cliGitProvider.ts +25 -0
- package/src/git-cli/exec/git.ts +120 -6
- package/src/git-cli/exec/gitQueue.ts +19 -17
- package/src/git-cli/parsers/logParser.ts +4 -1
- package/src/git-cli/providers/blame.ts +3 -8
- package/src/git-cli/providers/branches.ts +28 -8
- package/src/git-cli/providers/commits.ts +34 -2
- package/src/git-cli/providers/config.ts +38 -6
- package/src/git-cli/providers/graph.ts +107 -7
- package/src/git-cli/providers/maintenance.ts +2599 -0
- package/src/git-cli/providers/operations.ts +11 -0
- package/src/git-cli/providers/pausedOperations.ts +7 -2
- package/src/git-cli/providers/tags.ts +36 -1
- package/src/plus/agents/agentCapabilities.ts +286 -0
- package/src/plus/agents/providers/claudeCodeTranscript.ts +313 -58
- package/src/plus/agents/providers/{claudeCodeProvider.ts → gkAgentProvider.ts} +1123 -277
- package/src/plus/agents/types.ts +137 -40
- package/src/plus/ai/models/promptTemplates.ts +1 -1
- package/src/plus/ai/prompts.ts +62 -4
- package/src/plus/git-github/api/github.ts +404 -82
- package/src/plus/git-github/api/issueSearchQuery.ts +49 -1
- package/src/plus/git-github/providers/github/blame.ts +2 -1
- package/src/plus/integrations/collectionMetadata.ts +23 -1
- package/src/plus/integrations/context.ts +1 -1
- package/src/plus/integrations/index.ts +1 -0
- package/src/plus/integrations/integrationService.ts +29 -4
- package/src/plus/integrations/manager.ts +48 -0
- package/src/plus/integrations/models/gitHostIntegration.ts +165 -129
- package/src/plus/integrations/models/integration.ts +57 -22
- package/src/plus/integrations/models/issueCache.ts +29 -0
- package/src/plus/integrations/models/issueReads.ts +15 -0
- package/src/plus/integrations/models/issuesIntegration.ts +38 -8
- package/src/plus/integrations/providers/azureDevOps.ts +16 -13
- package/src/plus/integrations/providers/bitbucket-server.ts +4 -6
- package/src/plus/integrations/providers/bitbucket.ts +3 -4
- package/src/plus/integrations/providers/github.ts +23 -7
- package/src/plus/integrations/providers/gitlab.ts +4 -6
- package/src/plus/integrations/providers/jira.ts +52 -26
- package/src/plus/integrations/providers/jiraIssueByKey.ts +155 -0
- package/src/plus/integrations/providers/linear.ts +38 -25
- package/src/plus/integrations/providers/models.ts +17 -5
- package/src/plus/integrations/providers/providerErrors.ts +115 -0
- package/src/plus/integrations/providers/providersApi.ts +26 -68
- package/src/plus/integrations/providers/trello.ts +5 -4
- package/src/plus/integrations/providers/utils/providerPaging.ts +14 -7
- package/src/plus/integrations/reads/broaden.ts +282 -70
- package/src/plus/integrations/reads/filters.ts +39 -1
- package/src/plus/integrations/reads/issueBatch.ts +197 -0
- package/src/plus/integrations/reads/issueTracker.ts +26 -24
- package/src/plus/integrations/reads/sweeps.ts +19 -12
- package/src/plus/integrations/reads/trackerIssue.ts +105 -0
- package/src/plus/integrations/reads/warnings.ts +23 -17
- package/src/plus/integrations/results.ts +4 -20
- package/src/utils/promise.ts +15 -0
- package/src/utils/promiseCache.ts +43 -0
- package/src/utils/resourceUsage.ts +5 -0
- package/src/utils/string.ts +38 -1
- package/dist/plus/agents/providers/claudeCodeProvider.d.ts.map +0 -1
- package/dist/plus/agents/providers/claudeCodeProvider.js.map +0 -1
|
@@ -13,6 +13,7 @@ import type {
|
|
|
13
13
|
import type { RepositoryMetadata } from '../../../git/models/repositoryMetadata.js';
|
|
14
14
|
import type { ResourceDescriptor } from '../../../git/models/resourceDescriptor.js';
|
|
15
15
|
import type { PullRequestUrlIdentity } from '../../../git/utils/pullRequest.utils.js';
|
|
16
|
+
import { ensureArray } from '../../../utils/array.js';
|
|
16
17
|
import { isCancellationError } from '../../../utils/cancellation.js';
|
|
17
18
|
import { gate } from '../../../utils/decorators/gate.js';
|
|
18
19
|
import { trace } from '../../../utils/decorators/log.js';
|
|
@@ -22,7 +23,11 @@ import { getScopedLogger } from '../../../utils/logger.scoped.js';
|
|
|
22
23
|
import type { PagedResult } from '../../../utils/paging.js';
|
|
23
24
|
import type { ProviderAuthenticationSession } from '../authentication/models.js';
|
|
24
25
|
import { toTokenWithInfo } from '../authentication/models.js';
|
|
25
|
-
import {
|
|
26
|
+
import {
|
|
27
|
+
throwIfCallerContractError,
|
|
28
|
+
toCollectionFailureError,
|
|
29
|
+
toCollectionScopeFailure,
|
|
30
|
+
} from '../collectionMetadata.js';
|
|
26
31
|
import type { IntegrationIds } from '../constants.js';
|
|
27
32
|
import { GitCloudHostIntegrationId, GitSelfManagedHostIntegrationId } from '../constants.js';
|
|
28
33
|
import { toError } from '../errors.js';
|
|
@@ -50,7 +55,7 @@ import {
|
|
|
50
55
|
toProviderPullRequestStates,
|
|
51
56
|
} from '../providers/models.js';
|
|
52
57
|
import type { ProvidersApi } from '../providers/providersApi.js';
|
|
53
|
-
import { mergeCollectionMetadata } from '../providers/utils/providerPaging.js';
|
|
58
|
+
import { mergeCollectionMetadata, throwIfAllSettledFailed } from '../providers/utils/providerPaging.js';
|
|
54
59
|
import type {
|
|
55
60
|
IntegrationResult,
|
|
56
61
|
IntegrationType,
|
|
@@ -113,10 +118,24 @@ function getSelfManagedApiBaseUrl(
|
|
|
113
118
|
}
|
|
114
119
|
}
|
|
115
120
|
|
|
121
|
+
/** Read options for {@link GitHostIntegration.searchMyPullRequests} and the provider hook behind it. */
|
|
116
122
|
export type SearchMyPullRequestsOptions = {
|
|
123
|
+
/** Suppresses the user-facing notification when the read fails. */
|
|
124
|
+
silent?: boolean;
|
|
125
|
+
/**
|
|
126
|
+
* PR states to include (open/closed/merged/all). Providers that cannot express it in a single query
|
|
127
|
+
* filter the normalized results; omitted preserves the historical open-only behavior.
|
|
128
|
+
*/
|
|
129
|
+
state?: PullRequestStateFilter;
|
|
117
130
|
includeReviewRequested?: boolean;
|
|
118
131
|
};
|
|
119
132
|
|
|
133
|
+
/** Read options for {@link GitHostIntegration.searchPullRequests} and the provider hook behind it. */
|
|
134
|
+
export type SearchPullRequestsOptions = {
|
|
135
|
+
/** PR states to include; omitted preserves the provider's default. */
|
|
136
|
+
include?: PullRequestState[];
|
|
137
|
+
};
|
|
138
|
+
|
|
120
139
|
type MyPullRequestsForReposOptions = {
|
|
121
140
|
filters?: PullRequestFilter[];
|
|
122
141
|
cursor?: string;
|
|
@@ -747,10 +766,17 @@ export abstract class GitHostIntegration<
|
|
|
747
766
|
const customUrl =
|
|
748
767
|
options?.customUrl ?? getSelfManagedApiBaseUrl(providerId, session.domain || this.domain, session.protocol);
|
|
749
768
|
|
|
750
|
-
|
|
769
|
+
let api: ProvidersApi;
|
|
770
|
+
try {
|
|
771
|
+
api = await this.getProvidersApi();
|
|
772
|
+
} catch (ex) {
|
|
773
|
+
this.handleProviderException('getIssuesForRepos', ex, { scope: scope, connectionId: connectionId });
|
|
774
|
+
return { error: toError(ex), duration: performance.now() - start };
|
|
775
|
+
}
|
|
776
|
+
const repoIdsInput = api.isRepoIdsInput(reposOrRepoIds);
|
|
751
777
|
if (
|
|
752
778
|
providerId !== GitCloudHostIntegrationId.GitLab &&
|
|
753
|
-
(
|
|
779
|
+
(repoIdsInput ||
|
|
754
780
|
(isAzureDevOpsProvider(providerId) &&
|
|
755
781
|
!reposOrRepoIds.every(repo => repo.project != null && repo.namespace != null)))
|
|
756
782
|
) {
|
|
@@ -791,7 +817,10 @@ export abstract class GitHostIntegration<
|
|
|
791
817
|
try {
|
|
792
818
|
userAccount = await this.getFilterAccount(api, session, customUrl, organization);
|
|
793
819
|
} catch (ex) {
|
|
794
|
-
|
|
820
|
+
this.handleProviderException('getIssuesForRepos', ex, {
|
|
821
|
+
scope: scope,
|
|
822
|
+
connectionId: connectionId,
|
|
823
|
+
});
|
|
795
824
|
return { error: toError(ex), duration: performance.now() - start };
|
|
796
825
|
}
|
|
797
826
|
|
|
@@ -861,6 +890,7 @@ export abstract class GitHostIntegration<
|
|
|
861
890
|
return { projectInput: projectInput, results: results };
|
|
862
891
|
}),
|
|
863
892
|
);
|
|
893
|
+
throwIfAllSettledFailed(settled);
|
|
864
894
|
|
|
865
895
|
for (let i = 0; i < settled.length; i++) {
|
|
866
896
|
const outcome = settled[i];
|
|
@@ -904,6 +934,7 @@ export abstract class GitHostIntegration<
|
|
|
904
934
|
cursor.page = options.page;
|
|
905
935
|
}
|
|
906
936
|
|
|
937
|
+
this.resetRequestExceptionCount('getIssuesForRepos');
|
|
907
938
|
return {
|
|
908
939
|
value: {
|
|
909
940
|
values: data,
|
|
@@ -921,7 +952,10 @@ export abstract class GitHostIntegration<
|
|
|
921
952
|
duration: performance.now() - start,
|
|
922
953
|
};
|
|
923
954
|
} catch (ex) {
|
|
924
|
-
|
|
955
|
+
this.handleProviderException('getIssuesForRepos', ex, {
|
|
956
|
+
scope: scope,
|
|
957
|
+
connectionId: connectionId,
|
|
958
|
+
});
|
|
925
959
|
return { error: toError(ex), duration: performance.now() - start };
|
|
926
960
|
}
|
|
927
961
|
}
|
|
@@ -937,7 +971,10 @@ export abstract class GitHostIntegration<
|
|
|
937
971
|
try {
|
|
938
972
|
userAccount = await this.getFilterAccount(api, session, customUrl);
|
|
939
973
|
} catch (ex) {
|
|
940
|
-
|
|
974
|
+
this.handleProviderException('getIssuesForRepos', ex, {
|
|
975
|
+
scope: scope,
|
|
976
|
+
connectionId: connectionId,
|
|
977
|
+
});
|
|
941
978
|
return { error: toError(ex), duration: performance.now() - start };
|
|
942
979
|
}
|
|
943
980
|
|
|
@@ -964,7 +1001,7 @@ export abstract class GitHostIntegration<
|
|
|
964
1001
|
};
|
|
965
1002
|
}
|
|
966
1003
|
|
|
967
|
-
if (api.getProviderIssuesPagingMode(providerId) === PagingMode.Repo && !
|
|
1004
|
+
if (api.getProviderIssuesPagingMode(providerId) === PagingMode.Repo && !repoIdsInput) {
|
|
968
1005
|
const cursorInfo = this.parseCursorInfo<PagedRepoInput>(options?.cursor);
|
|
969
1006
|
const cursors: PagedRepoInput[] = cursorInfo.cursors ?? [];
|
|
970
1007
|
let repoInputs: PagedRepoInput[] = reposOrRepoIds.map(repo => ({ repo: repo, cursor: undefined }));
|
|
@@ -1001,6 +1038,7 @@ export abstract class GitHostIntegration<
|
|
|
1001
1038
|
return { repoInput: repoInput, results: results };
|
|
1002
1039
|
}),
|
|
1003
1040
|
);
|
|
1041
|
+
throwIfAllSettledFailed(settled);
|
|
1004
1042
|
|
|
1005
1043
|
for (let i = 0; i < settled.length; i++) {
|
|
1006
1044
|
const outcome = settled[i];
|
|
@@ -1038,6 +1076,7 @@ export abstract class GitHostIntegration<
|
|
|
1038
1076
|
cursor.page = options.page;
|
|
1039
1077
|
}
|
|
1040
1078
|
|
|
1079
|
+
this.resetRequestExceptionCount('getIssuesForRepos');
|
|
1041
1080
|
return {
|
|
1042
1081
|
value: {
|
|
1043
1082
|
values: data,
|
|
@@ -1055,13 +1094,17 @@ export abstract class GitHostIntegration<
|
|
|
1055
1094
|
duration: performance.now() - start,
|
|
1056
1095
|
};
|
|
1057
1096
|
} catch (ex) {
|
|
1058
|
-
|
|
1097
|
+
this.handleProviderException('getIssuesForRepos', ex, {
|
|
1098
|
+
scope: scope,
|
|
1099
|
+
connectionId: connectionId,
|
|
1100
|
+
});
|
|
1059
1101
|
return { error: toError(ex), duration: performance.now() - start };
|
|
1060
1102
|
}
|
|
1061
1103
|
}
|
|
1062
1104
|
|
|
1063
1105
|
try {
|
|
1064
|
-
const
|
|
1106
|
+
const tokenWithInfo = toTokenWithInfo(providerId, session);
|
|
1107
|
+
const result = await api.getIssuesForRepos(tokenWithInfo, reposOrRepoIds, {
|
|
1065
1108
|
...getIssuesOptions,
|
|
1066
1109
|
cursor: options?.cursor,
|
|
1067
1110
|
baseUrl: customUrl,
|
|
@@ -1070,9 +1113,28 @@ export abstract class GitHostIntegration<
|
|
|
1070
1113
|
states: states,
|
|
1071
1114
|
sort: options?.sort,
|
|
1072
1115
|
});
|
|
1116
|
+
const failures = result.metadata?.failures;
|
|
1117
|
+
if (
|
|
1118
|
+
repoIdsInput &&
|
|
1119
|
+
reposOrRepoIds.length > 0 &&
|
|
1120
|
+
result.values.length === 0 &&
|
|
1121
|
+
failures?.length === reposOrRepoIds.length
|
|
1122
|
+
) {
|
|
1123
|
+
const ex = toCollectionFailureError(failures[0], tokenWithInfo);
|
|
1124
|
+
this.handleProviderException('getIssuesForRepos', ex, {
|
|
1125
|
+
scope: scope,
|
|
1126
|
+
connectionId: connectionId,
|
|
1127
|
+
});
|
|
1128
|
+
return { error: ex, duration: performance.now() - start };
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
this.resetRequestExceptionCount('getIssuesForRepos');
|
|
1073
1132
|
return { value: result, duration: performance.now() - start };
|
|
1074
1133
|
} catch (ex) {
|
|
1075
|
-
|
|
1134
|
+
this.handleProviderException('getIssuesForRepos', ex, {
|
|
1135
|
+
scope: scope,
|
|
1136
|
+
connectionId: connectionId,
|
|
1137
|
+
});
|
|
1076
1138
|
return { error: toError(ex), duration: performance.now() - start };
|
|
1077
1139
|
}
|
|
1078
1140
|
}
|
|
@@ -1134,7 +1196,16 @@ export abstract class GitHostIntegration<
|
|
|
1134
1196
|
const customUrl =
|
|
1135
1197
|
options?.customUrl ?? getSelfManagedApiBaseUrl(providerId, session.domain || this.domain, session.protocol);
|
|
1136
1198
|
|
|
1137
|
-
|
|
1199
|
+
let api: ProvidersApi;
|
|
1200
|
+
try {
|
|
1201
|
+
api = await this.getProvidersApi();
|
|
1202
|
+
} catch (ex) {
|
|
1203
|
+
this.handleProviderException('getPullRequestsForRepos', ex, {
|
|
1204
|
+
scope: scope,
|
|
1205
|
+
connectionId: connectionId,
|
|
1206
|
+
});
|
|
1207
|
+
return { error: toError(ex), duration: performance.now() - start };
|
|
1208
|
+
}
|
|
1138
1209
|
if (
|
|
1139
1210
|
providerId !== GitCloudHostIntegrationId.GitLab &&
|
|
1140
1211
|
(api.isRepoIdsInput(reposOrRepoIds) ||
|
|
@@ -1182,14 +1253,20 @@ export abstract class GitHostIntegration<
|
|
|
1182
1253
|
try {
|
|
1183
1254
|
userAccount = await this.getFilterAccount(api, session, customUrl, organization);
|
|
1184
1255
|
} catch (ex) {
|
|
1185
|
-
|
|
1256
|
+
this.handleProviderException('getPullRequestsForRepos', ex, {
|
|
1257
|
+
scope: scope,
|
|
1258
|
+
connectionId: connectionId,
|
|
1259
|
+
});
|
|
1186
1260
|
return { error: toError(ex), duration: performance.now() - start };
|
|
1187
1261
|
}
|
|
1188
1262
|
} else {
|
|
1189
1263
|
try {
|
|
1190
1264
|
userAccount = await this.getFilterAccount(api, session, customUrl);
|
|
1191
1265
|
} catch (ex) {
|
|
1192
|
-
|
|
1266
|
+
this.handleProviderException('getPullRequestsForRepos', ex, {
|
|
1267
|
+
scope: scope,
|
|
1268
|
+
connectionId: connectionId,
|
|
1269
|
+
});
|
|
1193
1270
|
return { error: toError(ex), duration: performance.now() - start };
|
|
1194
1271
|
}
|
|
1195
1272
|
}
|
|
@@ -1298,6 +1375,7 @@ export abstract class GitHostIntegration<
|
|
|
1298
1375
|
return { repoInput: repoInput, results: results };
|
|
1299
1376
|
}),
|
|
1300
1377
|
);
|
|
1378
|
+
throwIfAllSettledFailed(settled);
|
|
1301
1379
|
|
|
1302
1380
|
// `allSettled` preserves order, so `settled[i]` is `repoInputs[i]`.
|
|
1303
1381
|
settled.forEach((outcome, i) => {
|
|
@@ -1338,6 +1416,7 @@ export abstract class GitHostIntegration<
|
|
|
1338
1416
|
cursor.page = options.page;
|
|
1339
1417
|
}
|
|
1340
1418
|
|
|
1419
|
+
this.resetRequestExceptionCount('getPullRequestsForRepos');
|
|
1341
1420
|
return {
|
|
1342
1421
|
value: {
|
|
1343
1422
|
values: data,
|
|
@@ -1355,7 +1434,10 @@ export abstract class GitHostIntegration<
|
|
|
1355
1434
|
duration: performance.now() - start,
|
|
1356
1435
|
};
|
|
1357
1436
|
} catch (ex) {
|
|
1358
|
-
|
|
1437
|
+
this.handleProviderException('getPullRequestsForRepos', ex, {
|
|
1438
|
+
scope: scope,
|
|
1439
|
+
connectionId: connectionId,
|
|
1440
|
+
});
|
|
1359
1441
|
return { error: toError(ex), duration: performance.now() - start };
|
|
1360
1442
|
}
|
|
1361
1443
|
}
|
|
@@ -1372,80 +1454,40 @@ export abstract class GitHostIntegration<
|
|
|
1372
1454
|
includeRemoteInfo: isAzureDevOpsProvider(providerId) ? true : undefined,
|
|
1373
1455
|
fields: options?.summary ? summaryPullRequestFields : undefined,
|
|
1374
1456
|
});
|
|
1457
|
+
this.resetRequestExceptionCount('getPullRequestsForRepos');
|
|
1375
1458
|
return { value: result, duration: performance.now() - start };
|
|
1376
1459
|
} catch (ex) {
|
|
1377
|
-
|
|
1460
|
+
this.handleProviderException('getPullRequestsForRepos', ex, {
|
|
1461
|
+
scope: scope,
|
|
1462
|
+
connectionId: connectionId,
|
|
1463
|
+
});
|
|
1378
1464
|
return { error: toError(ex), duration: performance.now() - start };
|
|
1379
1465
|
}
|
|
1380
1466
|
}
|
|
1381
1467
|
|
|
1382
|
-
|
|
1383
|
-
repo?: T,
|
|
1384
|
-
cancellation?: AbortSignal,
|
|
1385
|
-
silent?: boolean,
|
|
1386
|
-
connectionId?: string,
|
|
1387
|
-
state?: PullRequestStateFilter,
|
|
1388
|
-
options?: SearchMyPullRequestsOptions,
|
|
1389
|
-
): Promise<IntegrationResult<PullRequest[] | undefined>>;
|
|
1390
|
-
async searchMyPullRequests(
|
|
1391
|
-
repos?: T[],
|
|
1392
|
-
cancellation?: AbortSignal,
|
|
1393
|
-
silent?: boolean,
|
|
1394
|
-
connectionId?: string,
|
|
1395
|
-
state?: PullRequestStateFilter,
|
|
1396
|
-
options?: SearchMyPullRequestsOptions,
|
|
1397
|
-
): Promise<IntegrationResult<PullRequest[] | undefined>>;
|
|
1468
|
+
/** Account-wide (or repo-scoped) search for the current user's pull requests. */
|
|
1398
1469
|
@trace()
|
|
1399
1470
|
async searchMyPullRequests(
|
|
1400
1471
|
repos?: T | T[],
|
|
1401
1472
|
cancellation?: AbortSignal,
|
|
1402
|
-
|
|
1403
|
-
connectionId?: string,
|
|
1404
|
-
state?: PullRequestStateFilter,
|
|
1405
|
-
options?: SearchMyPullRequestsOptions,
|
|
1473
|
+
options?: SearchMyPullRequestsOptions & { connectionId?: string },
|
|
1406
1474
|
): Promise<IntegrationResult<PullRequest[] | undefined>> {
|
|
1407
1475
|
const scope = getScopedLogger();
|
|
1476
|
+
const { connectionId, ...searchOptions } = options ?? {};
|
|
1408
1477
|
// `connectionId` targets a specific account (multi-account); omitted reads the primary.
|
|
1409
1478
|
const session = await this.resolveReadSession(connectionId, scope);
|
|
1410
1479
|
if (session == null) return undefined;
|
|
1411
1480
|
|
|
1412
1481
|
const start = performance.now();
|
|
1413
1482
|
try {
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
session,
|
|
1421
|
-
repos != null ? (Array.isArray(repos) ? repos : [repos]) : undefined,
|
|
1422
|
-
cancellation,
|
|
1423
|
-
silent,
|
|
1424
|
-
state,
|
|
1425
|
-
options,
|
|
1426
|
-
);
|
|
1427
|
-
} else {
|
|
1428
|
-
result = {
|
|
1429
|
-
value: await this.searchProviderMyPullRequests(
|
|
1430
|
-
session,
|
|
1431
|
-
repos != null ? (Array.isArray(repos) ? repos : [repos]) : undefined,
|
|
1432
|
-
cancellation,
|
|
1433
|
-
silent,
|
|
1434
|
-
state,
|
|
1435
|
-
options,
|
|
1436
|
-
),
|
|
1437
|
-
};
|
|
1438
|
-
}
|
|
1483
|
+
const prs = await this.searchProviderMyPullRequests(
|
|
1484
|
+
session,
|
|
1485
|
+
ensureArray(repos),
|
|
1486
|
+
cancellation,
|
|
1487
|
+
searchOptions,
|
|
1488
|
+
);
|
|
1439
1489
|
this.resetRequestExceptionCount('searchMyPullRequests');
|
|
1440
|
-
|
|
1441
|
-
// matching branch explicitly; a missing result is treated as a successful empty read.
|
|
1442
|
-
if (result == null) {
|
|
1443
|
-
return { value: undefined, duration: performance.now() - start };
|
|
1444
|
-
}
|
|
1445
|
-
if (result.error != null) {
|
|
1446
|
-
return { error: result.error, duration: performance.now() - start };
|
|
1447
|
-
}
|
|
1448
|
-
return { value: result.value, duration: performance.now() - start };
|
|
1490
|
+
return { value: prs, duration: performance.now() - start };
|
|
1449
1491
|
} catch (ex) {
|
|
1450
1492
|
this.handleProviderException('searchMyPullRequests', ex, {
|
|
1451
1493
|
scope: scope,
|
|
@@ -1542,34 +1584,13 @@ export abstract class GitHostIntegration<
|
|
|
1542
1584
|
}
|
|
1543
1585
|
}
|
|
1544
1586
|
|
|
1545
|
-
// `state` selects which PR states to include (open/closed/merged/all). Providers that cannot express it
|
|
1546
|
-
// in a single query filter the normalized results; omitted preserves the historical open-only behavior.
|
|
1547
1587
|
protected abstract searchProviderMyPullRequests(
|
|
1548
1588
|
session: ProviderAuthenticationSession,
|
|
1549
1589
|
repos?: T[],
|
|
1550
1590
|
cancellation?: AbortSignal,
|
|
1551
|
-
silent?: boolean,
|
|
1552
|
-
state?: PullRequestStateFilter,
|
|
1553
1591
|
options?: SearchMyPullRequestsOptions,
|
|
1554
1592
|
): Promise<PullRequest[] | undefined>;
|
|
1555
1593
|
|
|
1556
|
-
/**
|
|
1557
|
-
* Optional metadata-aware counterpart of {@link searchProviderMyPullRequests}. Providers whose account-wide
|
|
1558
|
-
* "my PRs" read already produces {@link ProviderApiPagedResult} with completeness/failures can override
|
|
1559
|
-
* this to return a soft `{ value, error }` result so `searchMyPullRequests` surfaces partial data and a
|
|
1560
|
-
* warning instead of silently discarding the failure signal. The wrapper prefers this when present; the
|
|
1561
|
-
* abstract {@link searchProviderMyPullRequests} remains the required fallback for repo-scoped and
|
|
1562
|
-
* metadata-oblivious paths.
|
|
1563
|
-
*/
|
|
1564
|
-
protected searchProviderMyPullRequestsResult?(
|
|
1565
|
-
session: ProviderAuthenticationSession,
|
|
1566
|
-
repos?: T[],
|
|
1567
|
-
cancellation?: AbortSignal,
|
|
1568
|
-
silent?: boolean,
|
|
1569
|
-
state?: PullRequestStateFilter,
|
|
1570
|
-
options?: SearchMyPullRequestsOptions,
|
|
1571
|
-
): Promise<IntegrationResult<PullRequest[] | undefined>>;
|
|
1572
|
-
|
|
1573
1594
|
/**
|
|
1574
1595
|
* Result-returning wrapper for the filtered pull-request search. Errors become the soft
|
|
1575
1596
|
* `{ error }` branch so the public facade can preserve an empty account and a failed request as distinct
|
|
@@ -1618,49 +1639,16 @@ export abstract class GitHostIntegration<
|
|
|
1618
1639
|
cancellation?: AbortSignal,
|
|
1619
1640
|
): Promise<ProviderPullRequestSearchPage | undefined>;
|
|
1620
1641
|
|
|
1621
|
-
|
|
1622
|
-
searchQuery: string,
|
|
1623
|
-
repo?: T,
|
|
1624
|
-
cancellation?: AbortSignal,
|
|
1625
|
-
options?: { include?: PullRequestState[] },
|
|
1626
|
-
): Promise<PullRequest[] | undefined>;
|
|
1627
|
-
async searchPullRequests(
|
|
1628
|
-
searchQuery: string,
|
|
1629
|
-
repos?: T[],
|
|
1630
|
-
cancellation?: AbortSignal,
|
|
1631
|
-
options?: { include?: PullRequestState[] },
|
|
1632
|
-
): Promise<PullRequest[] | undefined>;
|
|
1633
|
-
async searchPullRequests(
|
|
1634
|
-
searchQuery: string,
|
|
1635
|
-
repo?: T,
|
|
1636
|
-
cancellation?: AbortSignal,
|
|
1637
|
-
connectionId?: string,
|
|
1638
|
-
options?: { include?: PullRequestState[] },
|
|
1639
|
-
): Promise<PullRequest[] | undefined>;
|
|
1640
|
-
async searchPullRequests(
|
|
1641
|
-
searchQuery: string,
|
|
1642
|
-
repos?: T[],
|
|
1643
|
-
cancellation?: AbortSignal,
|
|
1644
|
-
connectionId?: string,
|
|
1645
|
-
options?: { include?: PullRequestState[] },
|
|
1646
|
-
): Promise<PullRequest[] | undefined>;
|
|
1642
|
+
/** Free-text search across pull requests, optionally narrowed to `repos`. */
|
|
1647
1643
|
@trace()
|
|
1648
1644
|
async searchPullRequests(
|
|
1649
1645
|
searchQuery: string,
|
|
1650
1646
|
repos?: T | T[],
|
|
1651
1647
|
cancellation?: AbortSignal,
|
|
1652
|
-
|
|
1653
|
-
options?: { include?: PullRequestState[] },
|
|
1648
|
+
options?: SearchPullRequestsOptions & { connectionId?: string },
|
|
1654
1649
|
): Promise<PullRequest[] | undefined> {
|
|
1655
|
-
// `connectionId` (string) can be omitted when passing `options`; split the overlapping 4th arg.
|
|
1656
|
-
// When the 4th arg isn't the options object (a string `connectionId` or `undefined`), fall back to
|
|
1657
|
-
// the 5th-arg `options` so an explicit `undefined` connectionId still honors state filtering.
|
|
1658
|
-
const connectionId = typeof connectionIdOrOptions === 'string' ? connectionIdOrOptions : undefined;
|
|
1659
|
-
const searchOptions =
|
|
1660
|
-
connectionIdOrOptions != null && typeof connectionIdOrOptions !== 'string'
|
|
1661
|
-
? connectionIdOrOptions
|
|
1662
|
-
: options;
|
|
1663
1650
|
const scope = getScopedLogger();
|
|
1651
|
+
const { connectionId, ...searchOptions } = options ?? {};
|
|
1664
1652
|
// `connectionId` targets a specific account (multi-account); omitted reads the primary.
|
|
1665
1653
|
const session = await this.resolveReadSession(connectionId, scope);
|
|
1666
1654
|
if (session == null) return undefined;
|
|
@@ -1669,7 +1657,7 @@ export abstract class GitHostIntegration<
|
|
|
1669
1657
|
const prs = await this.searchProviderPullRequests?.(
|
|
1670
1658
|
session,
|
|
1671
1659
|
searchQuery,
|
|
1672
|
-
|
|
1660
|
+
ensureArray(repos),
|
|
1673
1661
|
cancellation,
|
|
1674
1662
|
searchOptions,
|
|
1675
1663
|
);
|
|
@@ -1686,7 +1674,7 @@ export abstract class GitHostIntegration<
|
|
|
1686
1674
|
searchQuery: string,
|
|
1687
1675
|
repos?: T[],
|
|
1688
1676
|
cancellation?: AbortSignal,
|
|
1689
|
-
options?:
|
|
1677
|
+
options?: SearchPullRequestsOptions,
|
|
1690
1678
|
): Promise<PullRequest[] | undefined>;
|
|
1691
1679
|
|
|
1692
1680
|
/**
|
|
@@ -1789,6 +1777,54 @@ export abstract class GitHostIntegration<
|
|
|
1789
1777
|
cancellation?: AbortSignal,
|
|
1790
1778
|
): Promise<(number | undefined)[] | undefined>;
|
|
1791
1779
|
|
|
1780
|
+
/**
|
|
1781
|
+
* Result-returning wrapper for the BATCH issue read: resolves several `(owner, repo, number)` coordinates in
|
|
1782
|
+
* one request. Recovers thrown errors into `{ error }` like the reads around it.
|
|
1783
|
+
*
|
|
1784
|
+
* Distinct from every search on this class, and deliberately so. A search answers "what matches"; this answers
|
|
1785
|
+
* "does this exact issue exist", which is the question a caller correlating a branch name to an issue is
|
|
1786
|
+
* actually asking. It has no result ceiling, no ordering and no cursor, and — the property that matters most —
|
|
1787
|
+
* an absent slot is a PROVEN ABSENCE rather than "not found within a page budget", so a caller can cache a
|
|
1788
|
+
* miss instead of re-walking for it forever.
|
|
1789
|
+
*
|
|
1790
|
+
* Results come back POSITIONALLY — one per input coordinate, in order — for the same reason
|
|
1791
|
+
* {@link countIssuesResult} does: a caller's key must never reach the provider query. `undefined` in a slot
|
|
1792
|
+
* means the issue does not exist or is not visible to this token, never that the read failed.
|
|
1793
|
+
*/
|
|
1794
|
+
async getIssuesBatchResult(
|
|
1795
|
+
coordinates: readonly { owner: string; repo: string; number: number }[],
|
|
1796
|
+
cancellation?: AbortSignal,
|
|
1797
|
+
connectionId?: string,
|
|
1798
|
+
): Promise<IntegrationResult<(IssueShape | undefined)[] | undefined>> {
|
|
1799
|
+
const scope = getScopedLogger();
|
|
1800
|
+
// `connectionId` targets a specific account (multi-account); omitted reads the primary.
|
|
1801
|
+
const session = await this.resolveReadSession(connectionId, scope);
|
|
1802
|
+
if (session == null) return undefined;
|
|
1803
|
+
|
|
1804
|
+
const start = performance.now();
|
|
1805
|
+
try {
|
|
1806
|
+
const issues = await this.getProviderIssuesBatch?.(session, coordinates, cancellation);
|
|
1807
|
+
this.resetRequestExceptionCount('getIssuesBatch');
|
|
1808
|
+
return { value: issues, duration: performance.now() - start };
|
|
1809
|
+
} catch (ex) {
|
|
1810
|
+
this.handleProviderException('getIssuesBatch', ex, { scope: scope, connectionId: connectionId });
|
|
1811
|
+
return { error: toError(ex), duration: performance.now() - start };
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
|
|
1815
|
+
/**
|
|
1816
|
+
* OPTIONAL: only a provider that can resolve SEVERAL issues by coordinate in one request implements this.
|
|
1817
|
+
* GitHub aliases its point read into one document; the SDK exposes only a singular `getIssue` for every other
|
|
1818
|
+
* provider, and there is no plural variant to build on. A provider that can't answer doesn't implement it and
|
|
1819
|
+
* the facade refuses the read, so a caller keeps its own per-issue path rather than being handed a batch that
|
|
1820
|
+
* silently degraded into N requests.
|
|
1821
|
+
*/
|
|
1822
|
+
protected getProviderIssuesBatch?(
|
|
1823
|
+
session: ProviderAuthenticationSession,
|
|
1824
|
+
coordinates: readonly { owner: string; repo: string; number: number }[],
|
|
1825
|
+
cancellation?: AbortSignal,
|
|
1826
|
+
): Promise<(IssueShape | undefined)[] | undefined>;
|
|
1827
|
+
|
|
1792
1828
|
/** The PR twin of {@link countIssuesResult}: counts each scope's pull requests, transferring none. */
|
|
1793
1829
|
async countPullRequestsResult(
|
|
1794
1830
|
scopes: readonly { repos?: ProviderRepoInput[]; org?: string; criteria?: PullRequestSearchCriteria }[],
|
|
@@ -11,6 +11,7 @@ import type { Disposable } from '../../../utils/disposable.js';
|
|
|
11
11
|
import type { Event } from '../../../utils/event.js';
|
|
12
12
|
import { Emitter } from '../../../utils/event.js';
|
|
13
13
|
import { fnv1aHash64 } from '../../../utils/hash.js';
|
|
14
|
+
import { Logger } from '../../../utils/logger.js';
|
|
14
15
|
import type { ScopedLogger } from '../../../utils/logger.scoped.js';
|
|
15
16
|
import { getScopedLogger } from '../../../utils/logger.scoped.js';
|
|
16
17
|
import type {
|
|
@@ -30,6 +31,7 @@ import type { Sources } from '../telemetry.js';
|
|
|
30
31
|
import { areDomainsOnSameHost } from '../utils/domain.utils.js';
|
|
31
32
|
import { isGitSelfManagedHostIntegrationId } from '../utils/integration.utils.js';
|
|
32
33
|
import type { GitHostIntegration } from './gitHostIntegration.js';
|
|
34
|
+
import { getCachedIssue } from './issueCache.js';
|
|
33
35
|
import type { AccountWideIssuesResult, SearchMyIssuesOptions } from './issueReads.js';
|
|
34
36
|
import type { IssuesIntegration } from './issuesIntegration.js';
|
|
35
37
|
|
|
@@ -65,6 +67,7 @@ type SyncReqUsecase = Exclude<
|
|
|
65
67
|
| 'getDefaultBranch'
|
|
66
68
|
| 'getIssue'
|
|
67
69
|
| 'getIssueOrPullRequest'
|
|
70
|
+
| 'getIssuesBatch'
|
|
68
71
|
| 'getIssuesForProject'
|
|
69
72
|
| 'getIssuesForRepos'
|
|
70
73
|
| 'getMyPullRequestsForUser'
|
|
@@ -491,7 +494,11 @@ export abstract class IntegrationBase<
|
|
|
491
494
|
): void {
|
|
492
495
|
if (isCancellationError(ex)) return;
|
|
493
496
|
|
|
494
|
-
options?.scope
|
|
497
|
+
if (options?.scope != null) {
|
|
498
|
+
options.scope.error(ex);
|
|
499
|
+
} else {
|
|
500
|
+
Logger.error(ex);
|
|
501
|
+
}
|
|
495
502
|
|
|
496
503
|
// A per-connection (multi-account) read resolved its session through `resolveReadSession`'s
|
|
497
504
|
// `connectionId` branch, which deliberately never touches the cached primary `_session`. So the
|
|
@@ -821,38 +828,66 @@ export abstract class IntegrationBase<
|
|
|
821
828
|
type: undefined | IssueOrPullRequestType,
|
|
822
829
|
): Promise<IssueOrPullRequest | undefined>;
|
|
823
830
|
|
|
824
|
-
@trace()
|
|
825
831
|
async getIssue(
|
|
826
832
|
resource: T,
|
|
827
833
|
id: string,
|
|
828
|
-
options?: { expiryOverride?: boolean | number },
|
|
834
|
+
options?: { connectionId?: string; expiryOverride?: boolean | number },
|
|
829
835
|
): Promise<Issue | undefined> {
|
|
830
|
-
|
|
836
|
+
return (await this.getIssueResult(resource, id, options))?.value;
|
|
837
|
+
}
|
|
831
838
|
|
|
832
|
-
|
|
833
|
-
|
|
839
|
+
getIssueResult(
|
|
840
|
+
resource: T,
|
|
841
|
+
id: string,
|
|
842
|
+
options?: { connectionId?: string; expiryOverride?: boolean | number },
|
|
843
|
+
): Promise<IntegrationResult<Issue | undefined>> {
|
|
844
|
+
return this.getIssueResultCore(resource, id, options, session => this.getProviderIssue(session, resource, id));
|
|
845
|
+
}
|
|
834
846
|
|
|
835
|
-
|
|
847
|
+
@trace()
|
|
848
|
+
protected async getIssueResultCore(
|
|
849
|
+
resource: ResourceDescriptor,
|
|
850
|
+
id: string,
|
|
851
|
+
options: { connectionId?: string; expiryOverride?: boolean | number } | undefined,
|
|
852
|
+
getProviderIssue: (session: ProviderAuthenticationSession) => Promise<Issue | undefined>,
|
|
853
|
+
): Promise<IntegrationResult<Issue | undefined>> {
|
|
854
|
+
const scope = getScopedLogger();
|
|
855
|
+
const { connectionId: requestedConnectionId, expiryOverride } = options ?? {};
|
|
856
|
+
const connectionId = requestedConnectionId || undefined;
|
|
857
|
+
const session = await this.resolveReadSession(connectionId, scope);
|
|
858
|
+
if (session == null) return undefined;
|
|
836
859
|
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
860
|
+
try {
|
|
861
|
+
const issue = await getCachedIssue({
|
|
862
|
+
cache: this.ctx.cache,
|
|
863
|
+
id: id,
|
|
864
|
+
resource: resource,
|
|
865
|
+
integration: this,
|
|
866
|
+
load: async () => {
|
|
843
867
|
try {
|
|
844
|
-
const
|
|
868
|
+
const issue = await getProviderIssue(session);
|
|
845
869
|
this.resetRequestExceptionCount('getIssue');
|
|
846
|
-
return
|
|
870
|
+
return issue;
|
|
847
871
|
} catch (ex) {
|
|
848
|
-
|
|
849
|
-
|
|
872
|
+
if (!isCancellationError(ex)) {
|
|
873
|
+
this.handleProviderException('getIssue', toError(ex), {
|
|
874
|
+
scope: scope,
|
|
875
|
+
connectionId: connectionId,
|
|
876
|
+
});
|
|
877
|
+
}
|
|
878
|
+
throw ex;
|
|
850
879
|
}
|
|
851
|
-
}
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
880
|
+
},
|
|
881
|
+
cacheOptions: {
|
|
882
|
+
connectionId: connectionId,
|
|
883
|
+
expiryOverride: expiryOverride,
|
|
884
|
+
etag: `${this.id}:${this.maybeConnected ?? false}:${this.getSessionFingerprint(session)}`,
|
|
885
|
+
},
|
|
886
|
+
});
|
|
887
|
+
return { value: issue };
|
|
888
|
+
} catch (ex) {
|
|
889
|
+
return { error: toError(ex) };
|
|
890
|
+
}
|
|
856
891
|
}
|
|
857
892
|
|
|
858
893
|
protected abstract getProviderIssue(
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Issue } from '../../../git/models/issue.js';
|
|
2
|
+
import type { ResourceDescriptor } from '../../../git/models/resourceDescriptor.js';
|
|
3
|
+
import type { IntegrationCacheProvider } from '../context.js';
|
|
4
|
+
|
|
5
|
+
export async function getCachedIssue(options: {
|
|
6
|
+
cache: IntegrationCacheProvider;
|
|
7
|
+
id: string;
|
|
8
|
+
resource: ResourceDescriptor;
|
|
9
|
+
integration: Parameters<IntegrationCacheProvider['getIssue']>[2];
|
|
10
|
+
load: () => Promise<Issue | undefined>;
|
|
11
|
+
cacheOptions: {
|
|
12
|
+
connectionId: string | undefined;
|
|
13
|
+
expiryOverride: boolean | number | undefined;
|
|
14
|
+
etag: string;
|
|
15
|
+
};
|
|
16
|
+
}): Promise<Issue | undefined> {
|
|
17
|
+
return options.cache.getIssue(
|
|
18
|
+
options.id,
|
|
19
|
+
options.resource,
|
|
20
|
+
options.integration,
|
|
21
|
+
cacheable => ({
|
|
22
|
+
value: options.load().catch((ex: unknown) => {
|
|
23
|
+
cacheable.invalidate();
|
|
24
|
+
throw ex;
|
|
25
|
+
}),
|
|
26
|
+
}),
|
|
27
|
+
options.cacheOptions,
|
|
28
|
+
);
|
|
29
|
+
}
|