@gitkraken/core-gitlens 0.9.4 → 0.9.6
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 +29 -1
- package/dist/git/models/issue.d.ts +25 -2
- package/dist/git/models/issue.js +3 -1
- package/dist/git/models/issue.js.map +1 -1
- package/dist/git/models/pullRequest.d.ts +62 -7
- package/dist/git/models/pullRequest.js +5 -1
- package/dist/git/models/pullRequest.js.map +1 -1
- package/dist/git/utils/issue.utils.d.ts +4 -0
- package/dist/git/utils/issue.utils.js +4 -0
- package/dist/git/utils/issue.utils.js.map +1 -1
- package/dist/git/utils/pullRequest.utils.d.ts +4 -0
- package/dist/git/utils/pullRequest.utils.js +8 -0
- package/dist/git/utils/pullRequest.utils.js.map +1 -1
- package/dist/plus/git-github/api/github.d.ts +64 -4
- package/dist/plus/git-github/api/github.js +232 -15
- package/dist/plus/git-github/api/github.js.map +1 -1
- package/dist/plus/git-github/models.d.ts +48 -6
- package/dist/plus/git-github/models.js +11 -10
- package/dist/plus/git-github/models.js.map +1 -1
- package/dist/plus/integrations/fieldPresence.d.ts +75 -0
- package/dist/plus/integrations/fieldPresence.js +381 -0
- package/dist/plus/integrations/fieldPresence.js.map +1 -0
- package/dist/plus/integrations/index.d.ts +6 -4
- package/dist/plus/integrations/index.js +2 -1
- package/dist/plus/integrations/index.js.map +1 -1
- package/dist/plus/integrations/integrationService.d.ts +7 -3
- package/dist/plus/integrations/integrationService.js.map +1 -1
- package/dist/plus/integrations/manager.d.ts +56 -6
- package/dist/plus/integrations/models/gitHostIntegration.d.ts +103 -9
- package/dist/plus/integrations/models/gitHostIntegration.js +116 -5
- package/dist/plus/integrations/models/gitHostIntegration.js.map +1 -1
- package/dist/plus/integrations/models/integration.d.ts +91 -4
- package/dist/plus/integrations/models/integration.js +56 -7
- package/dist/plus/integrations/models/integration.js.map +1 -1
- package/dist/plus/integrations/models/issuesIntegration.d.ts +44 -3
- package/dist/plus/integrations/models/issuesIntegration.js +51 -1
- package/dist/plus/integrations/models/issuesIntegration.js.map +1 -1
- package/dist/plus/integrations/providers/azure/azure.js +3 -3
- package/dist/plus/integrations/providers/azure/azure.js.map +1 -1
- package/dist/plus/integrations/providers/azure/models.d.ts +36 -4
- package/dist/plus/integrations/providers/azure/models.js +118 -8
- package/dist/plus/integrations/providers/azure/models.js.map +1 -1
- package/dist/plus/integrations/providers/azureDevOps.d.ts +102 -5
- package/dist/plus/integrations/providers/azureDevOps.js +264 -45
- package/dist/plus/integrations/providers/azureDevOps.js.map +1 -1
- package/dist/plus/integrations/providers/azureDevOpsServer.d.ts +30 -6
- package/dist/plus/integrations/providers/azureDevOpsServer.js +82 -21
- package/dist/plus/integrations/providers/azureDevOpsServer.js.map +1 -1
- package/dist/plus/integrations/providers/bitbucket/bitbucket.d.ts +21 -1
- package/dist/plus/integrations/providers/bitbucket/bitbucket.js +74 -10
- package/dist/plus/integrations/providers/bitbucket/bitbucket.js.map +1 -1
- package/dist/plus/integrations/providers/bitbucket/models.d.ts +40 -3
- package/dist/plus/integrations/providers/bitbucket/models.js +30 -7
- package/dist/plus/integrations/providers/bitbucket/models.js.map +1 -1
- package/dist/plus/integrations/providers/bitbucket-server/models.d.ts +2 -6
- package/dist/plus/integrations/providers/bitbucket-server/models.js +1 -3
- package/dist/plus/integrations/providers/bitbucket-server/models.js.map +1 -1
- package/dist/plus/integrations/providers/bitbucket-server/pullRequestSearch.d.ts +3 -1
- package/dist/plus/integrations/providers/bitbucket-server/pullRequestSearch.js +4 -1
- package/dist/plus/integrations/providers/bitbucket-server/pullRequestSearch.js.map +1 -1
- package/dist/plus/integrations/providers/bitbucket-server.d.ts +2 -2
- package/dist/plus/integrations/providers/bitbucket-server.js +7 -5
- package/dist/plus/integrations/providers/bitbucket-server.js.map +1 -1
- package/dist/plus/integrations/providers/bitbucket.d.ts +22 -2
- package/dist/plus/integrations/providers/bitbucket.js +29 -6
- package/dist/plus/integrations/providers/bitbucket.js.map +1 -1
- package/dist/plus/integrations/providers/github.d.ts +40 -3
- package/dist/plus/integrations/providers/github.js +133 -11
- package/dist/plus/integrations/providers/github.js.map +1 -1
- package/dist/plus/integrations/providers/gitlab/gitlab.d.ts +34 -1
- package/dist/plus/integrations/providers/gitlab/gitlab.js +118 -4
- package/dist/plus/integrations/providers/gitlab/gitlab.js.map +1 -1
- package/dist/plus/integrations/providers/gitlab/models.d.ts +70 -5
- package/dist/plus/integrations/providers/gitlab/models.js +106 -13
- package/dist/plus/integrations/providers/gitlab/models.js.map +1 -1
- package/dist/plus/integrations/providers/gitlab.d.ts +31 -2
- package/dist/plus/integrations/providers/gitlab.js +48 -8
- package/dist/plus/integrations/providers/gitlab.js.map +1 -1
- package/dist/plus/integrations/providers/jira-server.d.ts +1 -0
- package/dist/plus/integrations/providers/jira-server.js +9 -6
- package/dist/plus/integrations/providers/jira-server.js.map +1 -1
- package/dist/plus/integrations/providers/jira.d.ts +20 -1
- package/dist/plus/integrations/providers/jira.js +101 -6
- package/dist/plus/integrations/providers/jira.js.map +1 -1
- package/dist/plus/integrations/providers/jiraIssueByKey.d.ts +79 -0
- package/dist/plus/integrations/providers/jiraIssueByKey.js +58 -7
- package/dist/plus/integrations/providers/jiraIssueByKey.js.map +1 -1
- package/dist/plus/integrations/providers/linear.d.ts +19 -1
- package/dist/plus/integrations/providers/linear.js +97 -5
- package/dist/plus/integrations/providers/linear.js.map +1 -1
- package/dist/plus/integrations/providers/linearIssuesEtag.d.ts +42 -0
- package/dist/plus/integrations/providers/linearIssuesEtag.js +94 -0
- package/dist/plus/integrations/providers/linearIssuesEtag.js.map +1 -0
- package/dist/plus/integrations/providers/models.d.ts +51 -7
- package/dist/plus/integrations/providers/models.js +46 -17
- package/dist/plus/integrations/providers/models.js.map +1 -1
- package/dist/plus/integrations/providers/providerErrors.js +8 -1
- package/dist/plus/integrations/providers/providerErrors.js.map +1 -1
- package/dist/plus/integrations/providers/providersApi.d.ts +62 -3
- package/dist/plus/integrations/providers/providersApi.js +145 -4
- package/dist/plus/integrations/providers/providersApi.js.map +1 -1
- package/dist/plus/integrations/providers/pullRequestReviews.d.ts +13 -0
- package/dist/plus/integrations/providers/pullRequestReviews.js +30 -6
- package/dist/plus/integrations/providers/pullRequestReviews.js.map +1 -1
- package/dist/plus/integrations/providers/trello.js +10 -7
- package/dist/plus/integrations/providers/trello.js.map +1 -1
- package/dist/plus/integrations/providers/utils/providerPaging.d.ts +11 -0
- package/dist/plus/integrations/providers/utils/providerPaging.js +47 -1
- package/dist/plus/integrations/providers/utils/providerPaging.js.map +1 -1
- package/dist/plus/integrations/providers/utils.d.ts +1 -1
- package/dist/plus/integrations/reads/batchEtags.d.ts +69 -0
- package/dist/plus/integrations/reads/batchEtags.js +114 -0
- package/dist/plus/integrations/reads/batchEtags.js.map +1 -0
- package/dist/plus/integrations/reads/counts.js +2 -2
- package/dist/plus/integrations/reads/counts.js.map +1 -1
- package/dist/plus/integrations/reads/currentAccount.js +2 -2
- package/dist/plus/integrations/reads/currentAccount.js.map +1 -1
- package/dist/plus/integrations/reads/drains.d.ts +12 -3
- package/dist/plus/integrations/reads/drains.js +29 -5
- package/dist/plus/integrations/reads/drains.js.map +1 -1
- package/dist/plus/integrations/reads/etag.d.ts +26 -0
- package/dist/plus/integrations/reads/etag.js +108 -0
- package/dist/plus/integrations/reads/etag.js.map +1 -0
- package/dist/plus/integrations/reads/hierarchy.js +3 -3
- package/dist/plus/integrations/reads/hierarchy.js.map +1 -1
- package/dist/plus/integrations/reads/issueBatch.d.ts +47 -16
- package/dist/plus/integrations/reads/issueBatch.js +55 -87
- package/dist/plus/integrations/reads/issueBatch.js.map +1 -1
- package/dist/plus/integrations/reads/issueTracker.d.ts +1 -1
- package/dist/plus/integrations/reads/issueTracker.js +4 -4
- package/dist/plus/integrations/reads/issueTracker.js.map +1 -1
- package/dist/plus/integrations/reads/issues.d.ts +1 -1
- package/dist/plus/integrations/reads/issues.js +4 -4
- package/dist/plus/integrations/reads/issues.js.map +1 -1
- package/dist/plus/integrations/reads/pullRequestBatch.d.ts +44 -6
- package/dist/plus/integrations/reads/pullRequestBatch.js +31 -34
- package/dist/plus/integrations/reads/pullRequestBatch.js.map +1 -1
- package/dist/plus/integrations/reads/pullRequestBranches.d.ts +5 -2
- package/dist/plus/integrations/reads/pullRequestBranches.js +4 -3
- package/dist/plus/integrations/reads/pullRequestBranches.js.map +1 -1
- package/dist/plus/integrations/reads/pullRequests.js +8 -4
- package/dist/plus/integrations/reads/pullRequests.js.map +1 -1
- package/dist/plus/integrations/reads/sweeps.js +8 -4
- package/dist/plus/integrations/reads/sweeps.js.map +1 -1
- package/dist/plus/integrations/reads/warnings.d.ts +23 -8
- package/dist/plus/integrations/reads/warnings.js +43 -19
- package/dist/plus/integrations/reads/warnings.js.map +1 -1
- package/dist/plus/integrations/results.d.ts +12 -4
- package/dist/plus/integrations/results.js +2 -0
- package/dist/plus/integrations/results.js.map +1 -1
- package/docs/integrations.md +385 -23
- package/docs/kepler-read-api-parity.md +16 -2
- package/package.json +1 -1
|
@@ -4,8 +4,9 @@ import { PullRequestFilter, PullRequestSearchCriteria, PullRequestShape, PullReq
|
|
|
4
4
|
import { ConfiguredIntegrationDescriptor } from "./authentication/models.js";
|
|
5
5
|
import { IntegrationIds } from "./constants.js";
|
|
6
6
|
import { ConfiguredIntegrationsChangeEvent } from "./authentication/configuredIntegrationService.js";
|
|
7
|
-
import { IssueFilter } from "./providerFilters.js";
|
|
8
7
|
import { ConnectionStateChangeEvent, ProviderBroadenResult, ProviderOrganization, ProviderPagedResult, ProviderRepositoryShape, ProviderResult, ProviderSweepResult, ResolveRepositoryResult } from "./results.js";
|
|
8
|
+
import { IssueFilter } from "./providerFilters.js";
|
|
9
|
+
import { IssueEtagInclude, PullRequestEtagInclude } from "./models/integration.js";
|
|
9
10
|
import { IssueCountResult, IssueCountScope, PullRequestCountResult, PullRequestCountScope } from "./reads/counts.js";
|
|
10
11
|
import { CurrentAccountResult } from "./reads/currentAccount.js";
|
|
11
12
|
import { SupportedFilters } from "./reads/filters.js";
|
|
@@ -156,6 +157,12 @@ type PullRequestSweepCommonOptions = {
|
|
|
156
157
|
*/
|
|
157
158
|
includeReviews?: boolean;
|
|
158
159
|
forceSync?: boolean;
|
|
160
|
+
/**
|
|
161
|
+
* Page budget per provider. A stop at this budget with a resumable cursor is reported as
|
|
162
|
+
* `pagination-incomplete` with `recovery: 'page-budget'`. A part no budget reaches is reported beside it
|
|
163
|
+
* with `recovery: 'none'`: a `provider-limit` omission when the reported match count exceeds the provider's
|
|
164
|
+
* known result limit.
|
|
165
|
+
*/
|
|
159
166
|
maxPages?: number;
|
|
160
167
|
/**
|
|
161
168
|
* Fired once per target as it settles, for host-side per-provider attribution.
|
|
@@ -623,6 +630,16 @@ export interface IntegrationManager {
|
|
|
623
630
|
* outright — Bitbucket because it has no issues, Trello because its single-issue read can fall back to a capped
|
|
624
631
|
* board scan, which cannot prove an absence.
|
|
625
632
|
*
|
|
633
|
+
* Change detection: every found row carries an opaque `etag`; send it back on the target and, where the host has a
|
|
634
|
+
* cheap check (GitHub/GHE, GitLab, Azure DevOps, Jira Cloud and Linear so far), an issue whose etag still matches comes
|
|
635
|
+
* back `{ key, unchanged: true, etag }` without being read again. That costs up to three integration calls instead
|
|
636
|
+
* of one — the cheap check, a full read of the targets with no etag started alongside it, and a full read of the
|
|
637
|
+
* ones that changed — and still one when no target carries an etag. `etagIncludes: ['reactions']` widens the etag
|
|
638
|
+
* to the thumbs-up count, which a host changes without moving the update time; only GitHub/GHE and GitLab rows
|
|
639
|
+
* carry a real count, so it widens nothing elsewhere. A cheap check that fails falls through to the full read,
|
|
640
|
+
* except on an auth, rate-limit or connection failure, which drops its targets with that warning. See
|
|
641
|
+
* {@link IssueBatchResult}.
|
|
642
|
+
*
|
|
626
643
|
* A self-managed tracker (Jira Data Center) never falls back to the primary connection, unlike the paged reads:
|
|
627
644
|
* the call is refused unless `domain` names a host or `connectionId` a configured connection that has one, and
|
|
628
645
|
* every target's `resourceId` must name the host the read resolved to. Two self-hosted instances routinely issue
|
|
@@ -638,6 +655,12 @@ export interface IntegrationManager {
|
|
|
638
655
|
* for a self-managed tracker unless `connectionId` names a configured host — see above.
|
|
639
656
|
*/
|
|
640
657
|
domain?: string;
|
|
658
|
+
/**
|
|
659
|
+
* Widens every etag to the listed inputs; order and repeats don't matter, and an unknown value refuses the
|
|
660
|
+
* whole call. `'reactions'` is the thumbs-up count, and costs its field in the cheap check on GitHub/GHE and
|
|
661
|
+
* GitLab. Changes only which etag is computed (and the cheap check's selection); the full read is the same.
|
|
662
|
+
*/
|
|
663
|
+
etagIncludes?: readonly IssueEtagInclude[];
|
|
641
664
|
}): Promise<ProviderResult<IssueBatchResult>>;
|
|
642
665
|
/**
|
|
643
666
|
* Resolves several pull requests BY COORDINATE — `(owner, repo, number)`, plus `project` on Azure DevOps — in
|
|
@@ -663,6 +686,19 @@ export interface IntegrationManager {
|
|
|
663
686
|
* Request cost: GitHub/GHE resolve up to 25 targets per request (one aliased GraphQL document). Every other
|
|
664
687
|
* host costs one request per target, run with bounded concurrency; GitLab spends a second request to confirm a
|
|
665
688
|
* miss, and Azure DevOps one more per target (two for a fork) to fill clone URLs.
|
|
689
|
+
*
|
|
690
|
+
* Change detection: every found row carries an opaque `etag`; send it back on the target and, where the host has a
|
|
691
|
+
* cheap check (GitHub/GHE, a minimal aliased document; GitLab, one minimal request per project; Azure DevOps, one
|
|
692
|
+
* request per target without the clone URL reads, which fingerprints the title, description, target branch and
|
|
693
|
+
* reviewers as Azure DevOps reports no update time, but stays blind to comments; Bitbucket Cloud, one list request
|
|
694
|
+
* per repository per 50 pull requests), a pull request whose etag still matches comes back `{ key, unchanged: true,
|
|
695
|
+
* etag }` without being read again. That costs up to three integration calls instead of one — the cheap check, a
|
|
696
|
+
* full read of the targets with no etag started alongside it, and a full read of the ones that changed — and still
|
|
697
|
+
* one when no target carries an etag.
|
|
698
|
+
* `etagIncludes` widens the etag to the listed inputs (mergeability, review decision, check rollup), which a host
|
|
699
|
+
* changes without moving the update time and each of which costs its own fields in the cheap check (the review
|
|
700
|
+
* decision costs the most). A cheap check that fails falls through to the full read, except on an auth, rate-limit
|
|
701
|
+
* or connection failure, which drops its targets with that warning. See {@link PullRequestBatchResult}.
|
|
666
702
|
*/
|
|
667
703
|
getPullRequestsBatch(options: {
|
|
668
704
|
providerId: IntegrationIds;
|
|
@@ -671,6 +707,13 @@ export interface IntegrationManager {
|
|
|
671
707
|
connectionId?: string;
|
|
672
708
|
/** Self-managed host domain fallback; see {@link ProviderSweepTarget.domain}. */
|
|
673
709
|
domain?: string;
|
|
710
|
+
/**
|
|
711
|
+
* Widens every etag to the listed inputs; order and repeats don't matter, and an unknown value refuses the
|
|
712
|
+
* whole call. Each entry widens the etag to one input a host changes without moving the update time, and
|
|
713
|
+
* costs its own fields in the cheap check; `'checks'` is the check rollup. Changes only which etag is
|
|
714
|
+
* computed (and the cheap check's selection); the full read is the same.
|
|
715
|
+
*/
|
|
716
|
+
etagIncludes?: readonly PullRequestEtagInclude[];
|
|
674
717
|
}): Promise<ProviderResult<PullRequestBatchResult>>;
|
|
675
718
|
/**
|
|
676
719
|
* Finds, for each branch, every pull request whose head is that branch — in any state (open, closed or merged),
|
|
@@ -682,10 +725,14 @@ export interface IntegrationManager {
|
|
|
682
725
|
* branch in a fork, `headOwner` (the base repository's own owner, or none, means the base repository). A pull
|
|
683
726
|
* request matches only when its head repository is the right one — the base repository itself, or the fork
|
|
684
727
|
* `headOwner` owns — so a `main` in the base repository never claims every fork's `main`. The match is on the
|
|
685
|
-
* head branch NAME, so a merged pull request whose branch was since deleted is still found
|
|
728
|
+
* head branch NAME, so a merged pull request whose branch was since deleted is still found, and a fork is matched
|
|
729
|
+
* by its owner, so one whose fork was since deleted still matches that `headOwner`.
|
|
686
730
|
*
|
|
687
731
|
* Same result contract as {@link getPullRequestsBatch}, echoed under the caller's own `key`:
|
|
688
|
-
* - `{ key, pullRequests: [...] }` — found. `truncated` means
|
|
732
|
+
* - `{ key, pullRequests: [...] }` — found. `truncated` means a pull request that wasn't returned could still
|
|
733
|
+
* match. One exception on GitHub/GHE: on a branch name more forks share than the first request returned, a
|
|
734
|
+
* pull request from a since-deleted fork that request didn't return can't be found at all, so it can be
|
|
735
|
+
* missing from an answer, even an empty one, that isn't `truncated`.
|
|
689
736
|
* - `{ key, pullRequests: [] }` with no `truncated` — PROVEN NONE: the host answered and nothing matched, or the
|
|
690
737
|
* base repository doesn't exist or isn't visible to this connection. Safe to cache.
|
|
691
738
|
* - No item for a key, with `fetchFailed` and a warning — the read could not check. Never treat that as none.
|
|
@@ -695,9 +742,12 @@ export interface IntegrationManager {
|
|
|
695
742
|
* looks the branch ref up and so answers "none" once a merged branch is deleted. The caller owns caching.
|
|
696
743
|
*
|
|
697
744
|
* Request cost: GitHub/GHE answer up to 25 targets per request (one aliased GraphQL document, fetching up to 10
|
|
698
|
-
* full pull requests per target).
|
|
699
|
-
*
|
|
700
|
-
* {@link getPullRequestsBatch}'s own read,
|
|
745
|
+
* full pull requests per target). That document matches the branch name across every fork, so a target whose
|
|
746
|
+
* name more forks share than it returned costs one more REST request filtered by head owner, and a match only
|
|
747
|
+
* that request found is resolved through {@link getPullRequestsBatch}'s own read, so its row is identical to the
|
|
748
|
+
* others; the answer is the union of both requests' matches. Every other host costs one request per target, run
|
|
749
|
+
* with bounded concurrency; GitLab and Azure DevOps then resolve each matched pull request — typically 0–1 per
|
|
750
|
+
* branch — through {@link getPullRequestsBatch}'s own read, at that read's cost, so their rows are exactly its rows. Rows carry
|
|
701
751
|
* the list reads' fields on GitHub/GHE and Bitbucket Data Center and Bitbucket Cloud's by-id read's on
|
|
702
752
|
* Bitbucket Cloud. A `headOwner` naming another owner is refused on Bitbucket Data Center and Azure DevOps,
|
|
703
753
|
* where a fork can't be found by its owner.
|
|
@@ -12,9 +12,9 @@ import { IntegrationIds } from "../constants.js";
|
|
|
12
12
|
import { ProviderOrganization } from "../results.js";
|
|
13
13
|
import { ProviderScopeFailure } from "../collectionMetadata.js";
|
|
14
14
|
import { ProviderPullRequestCount, ProviderPullRequestSearchPage } from "./pullRequestReads.js";
|
|
15
|
-
import { MyIssuesForReposOptions, ProviderIssueSearchPage, ProviderSearchCount } from "./issueReads.js";
|
|
16
|
-
import { BatchSlot, IntegrationBase, IntegrationResult, IntegrationType } from "./integration.js";
|
|
17
15
|
import { ProviderApiPagedResult, ProviderHierarchyResult, ProviderIssue, ProviderPullRequest, ProviderRepoInput, ProviderReposInput, ProviderRepository } from "../providers/models.js";
|
|
16
|
+
import { MyIssuesForReposOptions, ProviderIssueSearchPage, ProviderSearchCount } from "./issueReads.js";
|
|
17
|
+
import { BatchSlot, IntegrationBase, IntegrationResult, IntegrationType, IssueEtagFields, IssueEtagInclude, PullRequestEtagFields, PullRequestEtagInclude } from "./integration.js";
|
|
18
18
|
import { CollectionMetadata } from "@gitkraken/provider-apis";
|
|
19
19
|
//#region ../plus/integrations/src/models/gitHostIntegration.d.ts
|
|
20
20
|
/** Read options for {@link GitHostIntegration.searchMyPullRequests} and the provider hook behind it. */
|
|
@@ -132,6 +132,14 @@ export declare abstract class GitHostIntegration<ID extends IntegrationIds = Int
|
|
|
132
132
|
* filters and no issue read is answering the same capability question twice, and the two must agree.
|
|
133
133
|
*/
|
|
134
134
|
get supportsIssues(): boolean;
|
|
135
|
+
/**
|
|
136
|
+
* Whether this host has the cheap check behind the batch pull request read's etags
|
|
137
|
+
* ({@link getProviderPullRequestsEtagFields}). The read decides before calling anything, so a host without one
|
|
138
|
+
* full-reads every target in a single call.
|
|
139
|
+
*/
|
|
140
|
+
get supportsPullRequestEtags(): boolean;
|
|
141
|
+
/** The issue twin of {@link supportsPullRequestEtags}: whether {@link getProviderIssuesEtagFields} exists. */
|
|
142
|
+
get supportsIssueEtags(): boolean;
|
|
135
143
|
/**
|
|
136
144
|
* Lists the organizations (orgs/workspaces/groups) the current user belongs to on this host.
|
|
137
145
|
* `truncated === true` means the defensive page-drain backstop stopped before the upstream listing was
|
|
@@ -271,8 +279,9 @@ export declare abstract class GitHostIntegration<ID extends IntegrationIds = Int
|
|
|
271
279
|
connectionId?: string;
|
|
272
280
|
}): Promise<IntegrationResult<PullRequest[] | undefined>>;
|
|
273
281
|
/**
|
|
274
|
-
* Account-wide, user-scoped counterpart of {@link getMyPullRequestsForReposResult} that returns
|
|
275
|
-
* `ProviderPullRequest
|
|
282
|
+
* Account-wide, user-scoped counterpart of {@link getMyPullRequestsForReposResult} that returns each host's raw
|
|
283
|
+
* rows: provider-apis' `ProviderPullRequest`, or GitHub's own `PullRequest`, still to be tagged for the read
|
|
284
|
+
* (`toPullRequestRow`). Unlike the repo-scoped core, this needs no
|
|
276
285
|
* `repos` — it reads the current user's pull requests across the account, so the ProviderBackend sweep
|
|
277
286
|
* can drive its Kanban "done" column even when no repositories are supplied (where the repo-scoped core
|
|
278
287
|
* rejects an empty `repos` input). Recovers thrown errors into `{ error }` so callers surface warnings.
|
|
@@ -285,10 +294,11 @@ export declare abstract class GitHostIntegration<ID extends IntegrationIds = Int
|
|
|
285
294
|
filters?: PullRequestFilter[];
|
|
286
295
|
/** Request only the stable list fields, omitting optional provider enrichments. */
|
|
287
296
|
summary?: boolean;
|
|
288
|
-
}, connectionId?: string): Promise<IntegrationResult<ProviderApiPagedResult<ProviderPullRequest> | undefined>>;
|
|
297
|
+
}, connectionId?: string): Promise<IntegrationResult<ProviderApiPagedResult<ProviderPullRequest | PullRequest> | undefined>>;
|
|
289
298
|
/**
|
|
290
299
|
* Reads the current user's pull requests across the whole account using each provider's native "my PRs"
|
|
291
|
-
* query, returning
|
|
300
|
+
* query, returning its raw rows (see {@link getMyPullRequestsForUserResult}). Without `filters`, the exact user
|
|
301
|
+
* scopes depend on provider-native
|
|
292
302
|
* behavior and options like `includeReviewRequested`. With `filters`, each member is an exact account-wide OR
|
|
293
303
|
* relationship validated by the facade before this provider hook is called. Optional: providers that can't
|
|
294
304
|
* express an account-wide user query leave it undefined and the surface falls back to repo-scoped.
|
|
@@ -307,7 +317,17 @@ export declare abstract class GitHostIntegration<ID extends IntegrationIds = Int
|
|
|
307
317
|
includeReviewRequested?: boolean;
|
|
308
318
|
filters?: PullRequestFilter[];
|
|
309
319
|
summary?: boolean;
|
|
310
|
-
}): Promise<ProviderApiPagedResult<ProviderPullRequest> | undefined>;
|
|
320
|
+
}): Promise<ProviderApiPagedResult<ProviderPullRequest | PullRequest> | undefined>;
|
|
321
|
+
/**
|
|
322
|
+
* The current account as each of `pullRequests` identifies its members, in order: what a raw row's
|
|
323
|
+
* `authoredByMe` and `viewer` are resolved against when it's mapped. Most hosts give a person one id, so every
|
|
324
|
+
* row gets the account itself; Azure DevOps Server answers per collection (see `AzureDevOpsServerIntegration`).
|
|
325
|
+
* Throws only when the account itself can't be read.
|
|
326
|
+
*/
|
|
327
|
+
getPullRequestViewers(pullRequests: readonly (ProviderPullRequest | PullRequest)[], connectionId?: string): Promise<({
|
|
328
|
+
id: string;
|
|
329
|
+
username?: string;
|
|
330
|
+
} | undefined)[]>;
|
|
311
331
|
/**
|
|
312
332
|
* Parses a Repo/Project paging cursor into its `cursors` bundle. Guards against valid JSON whose
|
|
313
333
|
* `cursors` is a truthy non-array (e.g. `{ "cursors": "..." }`), which would otherwise bypass the
|
|
@@ -423,7 +443,10 @@ export declare abstract class GitHostIntegration<ID extends IntegrationIds = Int
|
|
|
423
443
|
* as a failure against the integration's request-exception budget only when EVERY slot rejected, and not even
|
|
424
444
|
* then when a credential that checks out was refused by each target's own scope (`settleBatchRefusals`).
|
|
425
445
|
* Server errors and timeouts on the targets show one notice however many hit one, and cost a strike only as
|
|
426
|
-
* part of that whole-call failure (`reportDeferredRequestFailures`), so a call
|
|
446
|
+
* part of that whole-call failure (`reportDeferredRequestFailures`), so a call spends at most one. A batch read
|
|
447
|
+
* with etags makes up to two such calls (a full read of the targets without an etag, and a full read of the ones
|
|
448
|
+
* that changed), so it can spend two; its cheap check ({@link getIssuesEtagFieldsResult}) spends nothing unless
|
|
449
|
+
* the credential is refused.
|
|
427
450
|
*/
|
|
428
451
|
getIssuesBatchResult(coordinates: readonly {
|
|
429
452
|
owner: string;
|
|
@@ -458,7 +481,10 @@ export declare abstract class GitHostIntegration<ID extends IntegrationIds = Int
|
|
|
458
481
|
* call counts as a failure against the integration's request-exception budget only when EVERY slot rejected,
|
|
459
482
|
* and not even then when a credential that checks out was refused by each target's own scope
|
|
460
483
|
* (`settleBatchRefusals`). Server errors and timeouts on the targets show one notice however many hit one, and
|
|
461
|
-
* cost a strike only as part of that whole-call failure (`reportDeferredRequestFailures`)
|
|
484
|
+
* cost a strike only as part of that whole-call failure (`reportDeferredRequestFailures`), so one call spends at
|
|
485
|
+
* most one. A batch read with etags makes up to two such calls (a full read of the targets without an etag, and a
|
|
486
|
+
* full read of the ones that changed), so it can spend two; its cheap check
|
|
487
|
+
* ({@link getPullRequestsEtagFieldsResult}) spends nothing unless the credential is refused.
|
|
462
488
|
*/
|
|
463
489
|
getPullRequestsBatchResult(coordinates: readonly {
|
|
464
490
|
owner: string;
|
|
@@ -492,6 +518,74 @@ export declare abstract class GitHostIntegration<ID extends IntegrationIds = Int
|
|
|
492
518
|
username?: string;
|
|
493
519
|
};
|
|
494
520
|
} | undefined, cancellation?: AbortSignal): Promise<PromiseSettledResult<PullRequestShape | undefined>[] | undefined>;
|
|
521
|
+
/**
|
|
522
|
+
* Result-returning wrapper for the cheap check behind the batch issue read's etags: each coordinate's change
|
|
523
|
+
* state ({@link IssueEtagFields}), plus the inputs of each of `options.etagIncludes`, in ONE call to
|
|
524
|
+
* {@link getProviderIssuesEtagFields}. The slots mean what
|
|
525
|
+
* {@link getIssuesBatchResult}'s do — `fulfilled` with `undefined` is a PROVEN ABSENCE, `rejected` means that
|
|
526
|
+
* target could not be checked.
|
|
527
|
+
*
|
|
528
|
+
* Unlike there, failures other than a refused credential are never the call's: every slot comes back as it
|
|
529
|
+
* settled, even when none answered, so each failed target is judged by its own reason. Such failures spend no
|
|
530
|
+
* strike and show no notice, since the targets they touch fall through to the full read, which does both if the
|
|
531
|
+
* host really is failing, or are dropped as rate-limited or without a connection. Refusals are settled as there
|
|
532
|
+
* (`settleBatchRefusals` with `keepOtherFailures`), and only a refused credential fails the call, on the auth path
|
|
533
|
+
* (`handleEtagCheckException`). The failure budget is reset only when some target answered.
|
|
534
|
+
*/
|
|
535
|
+
getIssuesEtagFieldsResult(coordinates: readonly {
|
|
536
|
+
owner: string;
|
|
537
|
+
repo: string;
|
|
538
|
+
number: number;
|
|
539
|
+
project?: string;
|
|
540
|
+
}[], options: {
|
|
541
|
+
etagIncludes?: readonly IssueEtagInclude[];
|
|
542
|
+
}, cancellation?: AbortSignal, connectionId?: string): Promise<IntegrationResult<BatchSlot<IssueEtagFields | undefined>[] | undefined>>;
|
|
543
|
+
/**
|
|
544
|
+
* OPTIONAL: the cheap check behind the batch issue read's etags — one settled slot per input coordinate, in
|
|
545
|
+
* order, holding the issue's change state in the vocabulary {@link getProviderIssuesBatch}'s rows end in, so
|
|
546
|
+
* both reads compute the same etag. Each include's inputs are read only when it is listed in
|
|
547
|
+
* `options.etagIncludes`, and only where a full row carries them. `fulfilled` with `undefined` is a PROVEN
|
|
548
|
+
* ABSENCE, as there. A host implements this only where it is cheaper than the full read.
|
|
549
|
+
*/
|
|
550
|
+
protected getProviderIssuesEtagFields?(session: ProviderAuthenticationSession, coordinates: readonly {
|
|
551
|
+
owner: string;
|
|
552
|
+
repo: string;
|
|
553
|
+
number: number;
|
|
554
|
+
project?: string;
|
|
555
|
+
}[], options: {
|
|
556
|
+
etagIncludes?: readonly IssueEtagInclude[];
|
|
557
|
+
}, cancellation?: AbortSignal): Promise<PromiseSettledResult<IssueEtagFields | undefined>[] | undefined>;
|
|
558
|
+
/**
|
|
559
|
+
* Result-returning wrapper for the cheap check behind the batch pull request read's etags: each coordinate's
|
|
560
|
+
* change state ({@link PullRequestEtagFields}), plus the inputs of each of `options.etagIncludes`, in ONE call to
|
|
561
|
+
* {@link getProviderPullRequestsEtagFields}. The slots mean what {@link getPullRequestsBatchResult}'s do —
|
|
562
|
+
* `fulfilled` with `undefined` is a PROVEN ABSENCE, `rejected` means that target could not be checked. Failures
|
|
563
|
+
* are judged and budgeted as in {@link getIssuesEtagFieldsResult}: only a refused credential fails the call or
|
|
564
|
+
* spends a strike.
|
|
565
|
+
*/
|
|
566
|
+
getPullRequestsEtagFieldsResult(coordinates: readonly {
|
|
567
|
+
owner: string;
|
|
568
|
+
repo: string;
|
|
569
|
+
number: number;
|
|
570
|
+
project?: string;
|
|
571
|
+
}[], options: {
|
|
572
|
+
etagIncludes?: readonly PullRequestEtagInclude[];
|
|
573
|
+
}, cancellation?: AbortSignal, connectionId?: string): Promise<IntegrationResult<BatchSlot<PullRequestEtagFields | undefined>[] | undefined>>;
|
|
574
|
+
/**
|
|
575
|
+
* OPTIONAL: the cheap check behind the batch pull request read's etags — one settled slot per input coordinate,
|
|
576
|
+
* in order, holding the pull request's change state in the vocabulary {@link getProviderPullRequestsBatch}'s
|
|
577
|
+
* rows end in, after their WHOLE conversion chain, so both reads compute the same etag. Each include's inputs are
|
|
578
|
+
* read only when it is listed in `options.etagIncludes`. `fulfilled` with `undefined` is a PROVEN ABSENCE, as
|
|
579
|
+
* there. A host implements this only where it is cheaper than the full read.
|
|
580
|
+
*/
|
|
581
|
+
protected getProviderPullRequestsEtagFields?(session: ProviderAuthenticationSession, coordinates: readonly {
|
|
582
|
+
owner: string;
|
|
583
|
+
repo: string;
|
|
584
|
+
number: number;
|
|
585
|
+
project?: string;
|
|
586
|
+
}[], options: {
|
|
587
|
+
etagIncludes?: readonly PullRequestEtagInclude[];
|
|
588
|
+
}, cancellation?: AbortSignal): Promise<PromiseSettledResult<PullRequestEtagFields | undefined>[] | undefined>;
|
|
495
589
|
/**
|
|
496
590
|
* Result-returning wrapper for the pull-requests-by-branch read: for each target, every pull request whose head
|
|
497
591
|
* is that branch, in any state, in ONE call to {@link getProviderPullRequestsForBranches}. One settled slot
|
|
@@ -212,6 +212,18 @@ var GitHostIntegration = class extends IntegrationBase {
|
|
|
212
212
|
return true;
|
|
213
213
|
}
|
|
214
214
|
/**
|
|
215
|
+
* Whether this host has the cheap check behind the batch pull request read's etags
|
|
216
|
+
* ({@link getProviderPullRequestsEtagFields}). The read decides before calling anything, so a host without one
|
|
217
|
+
* full-reads every target in a single call.
|
|
218
|
+
*/
|
|
219
|
+
get supportsPullRequestEtags() {
|
|
220
|
+
return this.getProviderPullRequestsEtagFields != null;
|
|
221
|
+
}
|
|
222
|
+
/** The issue twin of {@link supportsPullRequestEtags}: whether {@link getProviderIssuesEtagFields} exists. */
|
|
223
|
+
get supportsIssueEtags() {
|
|
224
|
+
return this.getProviderIssuesEtagFields != null;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
215
227
|
* Lists the organizations (orgs/workspaces/groups) the current user belongs to on this host.
|
|
216
228
|
* `truncated === true` means the defensive page-drain backstop stopped before the upstream listing was
|
|
217
229
|
* exhausted.
|
|
@@ -760,7 +772,7 @@ var GitHostIntegration = class extends IntegrationBase {
|
|
|
760
772
|
value: void 0,
|
|
761
773
|
duration: result.duration
|
|
762
774
|
};
|
|
763
|
-
const values = result.value.values.map((issue) => toIssueShape(issue, this)).filter((issue) => issue != null);
|
|
775
|
+
const values = result.value.values.map((issue) => toIssueShape(issue, this, { projection: "repos" })).filter((issue) => issue != null);
|
|
764
776
|
return {
|
|
765
777
|
value: {
|
|
766
778
|
...result.value,
|
|
@@ -1012,8 +1024,9 @@ var GitHostIntegration = class extends IntegrationBase {
|
|
|
1012
1024
|
}
|
|
1013
1025
|
}
|
|
1014
1026
|
/**
|
|
1015
|
-
* Account-wide, user-scoped counterpart of {@link getMyPullRequestsForReposResult} that returns
|
|
1016
|
-
* `ProviderPullRequest
|
|
1027
|
+
* Account-wide, user-scoped counterpart of {@link getMyPullRequestsForReposResult} that returns each host's raw
|
|
1028
|
+
* rows: provider-apis' `ProviderPullRequest`, or GitHub's own `PullRequest`, still to be tagged for the read
|
|
1029
|
+
* (`toPullRequestRow`). Unlike the repo-scoped core, this needs no
|
|
1017
1030
|
* `repos` — it reads the current user's pull requests across the account, so the ProviderBackend sweep
|
|
1018
1031
|
* can drive its Kanban "done" column even when no repositories are supplied (where the repo-scoped core
|
|
1019
1032
|
* rejects an empty `repos` input). Recovers thrown errors into `{ error }` so callers surface warnings.
|
|
@@ -1044,6 +1057,20 @@ var GitHostIntegration = class extends IntegrationBase {
|
|
|
1044
1057
|
}
|
|
1045
1058
|
}
|
|
1046
1059
|
/**
|
|
1060
|
+
* The current account as each of `pullRequests` identifies its members, in order: what a raw row's
|
|
1061
|
+
* `authoredByMe` and `viewer` are resolved against when it's mapped. Most hosts give a person one id, so every
|
|
1062
|
+
* row gets the account itself; Azure DevOps Server answers per collection (see `AzureDevOpsServerIntegration`).
|
|
1063
|
+
* Throws only when the account itself can't be read.
|
|
1064
|
+
*/
|
|
1065
|
+
async getPullRequestViewers(pullRequests, connectionId) {
|
|
1066
|
+
const account = await this.getCurrentAccount({ connectionId });
|
|
1067
|
+
const viewer = account != null ? {
|
|
1068
|
+
id: account.id,
|
|
1069
|
+
username: account.username
|
|
1070
|
+
} : void 0;
|
|
1071
|
+
return pullRequests.map(() => viewer);
|
|
1072
|
+
}
|
|
1073
|
+
/**
|
|
1047
1074
|
* Parses a Repo/Project paging cursor into its `cursors` bundle. Guards against valid JSON whose
|
|
1048
1075
|
* `cursors` is a truthy non-array (e.g. `{ "cursors": "..." }`), which would otherwise bypass the
|
|
1049
1076
|
* `?? []` fallback at call sites and flow into `.map()` downstream, throwing instead of degrading to
|
|
@@ -1187,7 +1214,10 @@ var GitHostIntegration = class extends IntegrationBase {
|
|
|
1187
1214
|
* as a failure against the integration's request-exception budget only when EVERY slot rejected, and not even
|
|
1188
1215
|
* then when a credential that checks out was refused by each target's own scope (`settleBatchRefusals`).
|
|
1189
1216
|
* Server errors and timeouts on the targets show one notice however many hit one, and cost a strike only as
|
|
1190
|
-
* part of that whole-call failure (`reportDeferredRequestFailures`), so a call
|
|
1217
|
+
* part of that whole-call failure (`reportDeferredRequestFailures`), so a call spends at most one. A batch read
|
|
1218
|
+
* with etags makes up to two such calls (a full read of the targets without an etag, and a full read of the ones
|
|
1219
|
+
* that changed), so it can spend two; its cheap check ({@link getIssuesEtagFieldsResult}) spends nothing unless
|
|
1220
|
+
* the credential is refused.
|
|
1191
1221
|
*/
|
|
1192
1222
|
async getIssuesBatchResult(coordinates, cancellation, connectionId) {
|
|
1193
1223
|
const scope = getScopedLogger();
|
|
@@ -1235,7 +1265,10 @@ var GitHostIntegration = class extends IntegrationBase {
|
|
|
1235
1265
|
* call counts as a failure against the integration's request-exception budget only when EVERY slot rejected,
|
|
1236
1266
|
* and not even then when a credential that checks out was refused by each target's own scope
|
|
1237
1267
|
* (`settleBatchRefusals`). Server errors and timeouts on the targets show one notice however many hit one, and
|
|
1238
|
-
* cost a strike only as part of that whole-call failure (`reportDeferredRequestFailures`)
|
|
1268
|
+
* cost a strike only as part of that whole-call failure (`reportDeferredRequestFailures`), so one call spends at
|
|
1269
|
+
* most one. A batch read with etags makes up to two such calls (a full read of the targets without an etag, and a
|
|
1270
|
+
* full read of the ones that changed), so it can spend two; its cheap check
|
|
1271
|
+
* ({@link getPullRequestsEtagFieldsResult}) spends nothing unless the credential is refused.
|
|
1239
1272
|
*/
|
|
1240
1273
|
async getPullRequestsBatchResult(coordinates, options, cancellation, connectionId) {
|
|
1241
1274
|
const scope = getScopedLogger();
|
|
@@ -1272,6 +1305,84 @@ var GitHostIntegration = class extends IntegrationBase {
|
|
|
1272
1305
|
}
|
|
1273
1306
|
}
|
|
1274
1307
|
/**
|
|
1308
|
+
* Result-returning wrapper for the cheap check behind the batch issue read's etags: each coordinate's change
|
|
1309
|
+
* state ({@link IssueEtagFields}), plus the inputs of each of `options.etagIncludes`, in ONE call to
|
|
1310
|
+
* {@link getProviderIssuesEtagFields}. The slots mean what
|
|
1311
|
+
* {@link getIssuesBatchResult}'s do — `fulfilled` with `undefined` is a PROVEN ABSENCE, `rejected` means that
|
|
1312
|
+
* target could not be checked.
|
|
1313
|
+
*
|
|
1314
|
+
* Unlike there, failures other than a refused credential are never the call's: every slot comes back as it
|
|
1315
|
+
* settled, even when none answered, so each failed target is judged by its own reason. Such failures spend no
|
|
1316
|
+
* strike and show no notice, since the targets they touch fall through to the full read, which does both if the
|
|
1317
|
+
* host really is failing, or are dropped as rate-limited or without a connection. Refusals are settled as there
|
|
1318
|
+
* (`settleBatchRefusals` with `keepOtherFailures`), and only a refused credential fails the call, on the auth path
|
|
1319
|
+
* (`handleEtagCheckException`). The failure budget is reset only when some target answered.
|
|
1320
|
+
*/
|
|
1321
|
+
async getIssuesEtagFieldsResult(coordinates, options, cancellation, connectionId) {
|
|
1322
|
+
const scope = getScopedLogger();
|
|
1323
|
+
const session = await this.resolveReadSession(connectionId, scope);
|
|
1324
|
+
if (session == null) return void 0;
|
|
1325
|
+
const start = performance.now();
|
|
1326
|
+
try {
|
|
1327
|
+
const slots = await this.getProviderIssuesEtagFields?.(session, coordinates, options, cancellation);
|
|
1328
|
+
if (slots == null) return {
|
|
1329
|
+
value: void 0,
|
|
1330
|
+
duration: performance.now() - start
|
|
1331
|
+
};
|
|
1332
|
+
const settled = await this.settleBatchRefusals(session, coordinates, slots, { keepOtherFailures: true });
|
|
1333
|
+
if (slots.some((slot) => slot.status === "fulfilled")) this.resetRequestExceptionCount("getIssuesEtagFields");
|
|
1334
|
+
return {
|
|
1335
|
+
value: settled,
|
|
1336
|
+
duration: performance.now() - start
|
|
1337
|
+
};
|
|
1338
|
+
} catch (ex) {
|
|
1339
|
+
this.handleEtagCheckException("getIssuesEtagFields", ex, {
|
|
1340
|
+
scope,
|
|
1341
|
+
connectionId
|
|
1342
|
+
});
|
|
1343
|
+
return {
|
|
1344
|
+
error: toError(ex),
|
|
1345
|
+
duration: performance.now() - start
|
|
1346
|
+
};
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
/**
|
|
1350
|
+
* Result-returning wrapper for the cheap check behind the batch pull request read's etags: each coordinate's
|
|
1351
|
+
* change state ({@link PullRequestEtagFields}), plus the inputs of each of `options.etagIncludes`, in ONE call to
|
|
1352
|
+
* {@link getProviderPullRequestsEtagFields}. The slots mean what {@link getPullRequestsBatchResult}'s do —
|
|
1353
|
+
* `fulfilled` with `undefined` is a PROVEN ABSENCE, `rejected` means that target could not be checked. Failures
|
|
1354
|
+
* are judged and budgeted as in {@link getIssuesEtagFieldsResult}: only a refused credential fails the call or
|
|
1355
|
+
* spends a strike.
|
|
1356
|
+
*/
|
|
1357
|
+
async getPullRequestsEtagFieldsResult(coordinates, options, cancellation, connectionId) {
|
|
1358
|
+
const scope = getScopedLogger();
|
|
1359
|
+
const session = await this.resolveReadSession(connectionId, scope);
|
|
1360
|
+
if (session == null) return void 0;
|
|
1361
|
+
const start = performance.now();
|
|
1362
|
+
try {
|
|
1363
|
+
const slots = await this.getProviderPullRequestsEtagFields?.(session, coordinates, options, cancellation);
|
|
1364
|
+
if (slots == null) return {
|
|
1365
|
+
value: void 0,
|
|
1366
|
+
duration: performance.now() - start
|
|
1367
|
+
};
|
|
1368
|
+
const settled = await this.settleBatchRefusals(session, coordinates, slots, { keepOtherFailures: true });
|
|
1369
|
+
if (slots.some((slot) => slot.status === "fulfilled")) this.resetRequestExceptionCount("getPullRequestsEtagFields");
|
|
1370
|
+
return {
|
|
1371
|
+
value: settled,
|
|
1372
|
+
duration: performance.now() - start
|
|
1373
|
+
};
|
|
1374
|
+
} catch (ex) {
|
|
1375
|
+
this.handleEtagCheckException("getPullRequestsEtagFields", ex, {
|
|
1376
|
+
scope,
|
|
1377
|
+
connectionId
|
|
1378
|
+
});
|
|
1379
|
+
return {
|
|
1380
|
+
error: toError(ex),
|
|
1381
|
+
duration: performance.now() - start
|
|
1382
|
+
};
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
/**
|
|
1275
1386
|
* Result-returning wrapper for the pull-requests-by-branch read: for each target, every pull request whose head
|
|
1276
1387
|
* is that branch, in any state, in ONE call to {@link getProviderPullRequestsForBranches}. One settled slot
|
|
1277
1388
|
* per target: `fulfilled` with an empty list means the host answered and nothing matched; `rejected` means
|