@gitkraken/core-gitlens 0.7.1 → 0.8.0

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.
Files changed (188) hide show
  1. package/CHANGELOG.md +48 -1
  2. package/dist/git/cache.d.ts +18 -5
  3. package/dist/git/cache.js +26 -8
  4. package/dist/git/cache.js.map +1 -1
  5. package/dist/git/context.d.ts +5 -1
  6. package/dist/git/context.js.map +1 -1
  7. package/dist/git/errors.d.ts +28 -1
  8. package/dist/git/errors.js +45 -1
  9. package/dist/git/errors.js.map +1 -1
  10. package/dist/git/providers/branches.d.ts +5 -1
  11. package/dist/git/providers/commits.d.ts +24 -1
  12. package/dist/git/providers/config.d.ts +7 -1
  13. package/dist/git/providers/operations.d.ts +6 -0
  14. package/dist/git/providers/provider.d.ts +17 -0
  15. package/dist/git/providers/refs.d.ts +38 -3
  16. package/dist/git/providers/revision.d.ts +5 -1
  17. package/dist/git/providers/staging.d.ts +12 -0
  18. package/dist/git/providers/worktrees.d.ts +23 -3
  19. package/dist/git/run.types.d.ts +6 -0
  20. package/dist/git-cli/cliGitProvider.d.ts +17 -1
  21. package/dist/git-cli/cliGitProvider.js +37 -1
  22. package/dist/git-cli/cliGitProvider.js.map +1 -1
  23. package/dist/git-cli/exec/git.d.ts +12 -2
  24. package/dist/git-cli/exec/git.js +48 -17
  25. package/dist/git-cli/exec/git.js.map +1 -1
  26. package/dist/git-cli/exec/gitQueue.d.ts +4 -1
  27. package/dist/git-cli/exec/gitQueue.js +1 -1
  28. package/dist/git-cli/exec/gitQueue.js.map +1 -1
  29. package/dist/git-cli/providers/branches.d.ts +10 -1
  30. package/dist/git-cli/providers/branches.js +15 -8
  31. package/dist/git-cli/providers/branches.js.map +1 -1
  32. package/dist/git-cli/providers/commits.d.ts +23 -1
  33. package/dist/git-cli/providers/commits.js +57 -8
  34. package/dist/git-cli/providers/commits.js.map +1 -1
  35. package/dist/git-cli/providers/config.js +4 -3
  36. package/dist/git-cli/providers/config.js.map +1 -1
  37. package/dist/git-cli/providers/operations.d.ts +1 -0
  38. package/dist/git-cli/providers/operations.js +39 -3
  39. package/dist/git-cli/providers/operations.js.map +1 -1
  40. package/dist/git-cli/providers/patch.js +20 -41
  41. package/dist/git-cli/providers/patch.js.map +1 -1
  42. package/dist/git-cli/providers/pausedOperations.js +2 -2
  43. package/dist/git-cli/providers/pausedOperations.js.map +1 -1
  44. package/dist/git-cli/providers/refs.d.ts +15 -3
  45. package/dist/git-cli/providers/refs.js +115 -10
  46. package/dist/git-cli/providers/refs.js.map +1 -1
  47. package/dist/git-cli/providers/revision.d.ts +3 -1
  48. package/dist/git-cli/providers/revision.js +9 -5
  49. package/dist/git-cli/providers/revision.js.map +1 -1
  50. package/dist/git-cli/providers/staging.d.ts +8 -0
  51. package/dist/git-cli/providers/staging.js +59 -7
  52. package/dist/git-cli/providers/staging.js.map +1 -1
  53. package/dist/git-cli/providers/worktrees.d.ts +31 -2
  54. package/dist/git-cli/providers/worktrees.js +75 -7
  55. package/dist/git-cli/providers/worktrees.js.map +1 -1
  56. package/dist/ipc/discovery.js +1 -1
  57. package/dist/plus/agents/providers/claudeCodeTranscript.js +6 -6
  58. package/dist/plus/agents/providers/claudeCodeTranscript.js.map +1 -1
  59. package/dist/plus/ai/providers/openAICompatibleProviderBase.js +1 -1
  60. package/dist/plus/git-github/api/github.d.ts +64 -3
  61. package/dist/plus/git-github/api/github.js +237 -24
  62. package/dist/plus/git-github/api/github.js.map +1 -1
  63. package/dist/plus/git-github/providers/github/branches.d.ts +3 -1
  64. package/dist/plus/git-github/providers/github/branches.js +2 -1
  65. package/dist/plus/git-github/providers/github/branches.js.map +1 -1
  66. package/dist/plus/git-github/providers/github/refs.d.ts +10 -3
  67. package/dist/plus/git-github/providers/github/refs.js +4 -4
  68. package/dist/plus/git-github/providers/github/refs.js.map +1 -1
  69. package/dist/plus/git-github/providers/github/revision.d.ts +3 -1
  70. package/dist/plus/git-github/providers/github/revision.js +1 -1
  71. package/dist/plus/git-github/providers/github/revision.js.map +1 -1
  72. package/dist/plus/integrations/collectionMetadata.d.ts +48 -3
  73. package/dist/plus/integrations/collectionMetadata.js +138 -8
  74. package/dist/plus/integrations/collectionMetadata.js.map +1 -1
  75. package/dist/plus/integrations/errors.d.ts +3 -1
  76. package/dist/plus/integrations/errors.js +7 -3
  77. package/dist/plus/integrations/errors.js.map +1 -1
  78. package/dist/plus/integrations/index.d.ts +6 -3
  79. package/dist/plus/integrations/index.js.map +1 -1
  80. package/dist/plus/integrations/integrationService.d.ts +36 -10
  81. package/dist/plus/integrations/integrationService.js +16 -3
  82. package/dist/plus/integrations/integrationService.js.map +1 -1
  83. package/dist/plus/integrations/manager.d.ts +107 -37
  84. package/dist/plus/integrations/models/gitHostIntegration.d.ts +129 -14
  85. package/dist/plus/integrations/models/gitHostIntegration.js +142 -18
  86. package/dist/plus/integrations/models/gitHostIntegration.js.map +1 -1
  87. package/dist/plus/integrations/models/integration.d.ts +117 -11
  88. package/dist/plus/integrations/models/integration.js +175 -13
  89. package/dist/plus/integrations/models/integration.js.map +1 -1
  90. package/dist/plus/integrations/models/issuesIntegration.d.ts +18 -5
  91. package/dist/plus/integrations/models/issuesIntegration.js +42 -10
  92. package/dist/plus/integrations/models/issuesIntegration.js.map +1 -1
  93. package/dist/plus/integrations/providers/azure/azure.d.ts +1 -1
  94. package/dist/plus/integrations/providers/azure/azure.js +14 -18
  95. package/dist/plus/integrations/providers/azure/azure.js.map +1 -1
  96. package/dist/plus/integrations/providers/azure/models.d.ts +29 -0
  97. package/dist/plus/integrations/providers/azure/models.js +112 -1
  98. package/dist/plus/integrations/providers/azure/models.js.map +1 -1
  99. package/dist/plus/integrations/providers/azureDevOps.d.ts +73 -3
  100. package/dist/plus/integrations/providers/azureDevOps.js +117 -3
  101. package/dist/plus/integrations/providers/azureDevOps.js.map +1 -1
  102. package/dist/plus/integrations/providers/azureDevOpsServer.js +2 -1
  103. package/dist/plus/integrations/providers/azureDevOpsServer.js.map +1 -1
  104. package/dist/plus/integrations/providers/bitbucket/bitbucket.d.ts +61 -0
  105. package/dist/plus/integrations/providers/bitbucket/bitbucket.js +165 -23
  106. package/dist/plus/integrations/providers/bitbucket/bitbucket.js.map +1 -1
  107. package/dist/plus/integrations/providers/bitbucket/models.d.ts +6 -1
  108. package/dist/plus/integrations/providers/bitbucket/models.js +4 -3
  109. package/dist/plus/integrations/providers/bitbucket/models.js.map +1 -1
  110. package/dist/plus/integrations/providers/bitbucket-server/pullRequestSearch.js +2 -2
  111. package/dist/plus/integrations/providers/bitbucket-server/pullRequestSearch.js.map +1 -1
  112. package/dist/plus/integrations/providers/bitbucket-server.d.ts +48 -2
  113. package/dist/plus/integrations/providers/bitbucket-server.js +51 -1
  114. package/dist/plus/integrations/providers/bitbucket-server.js.map +1 -1
  115. package/dist/plus/integrations/providers/bitbucket.d.ts +45 -2
  116. package/dist/plus/integrations/providers/bitbucket.js +41 -2
  117. package/dist/plus/integrations/providers/bitbucket.js.map +1 -1
  118. package/dist/plus/integrations/providers/github.d.ts +49 -5
  119. package/dist/plus/integrations/providers/github.js +102 -7
  120. package/dist/plus/integrations/providers/github.js.map +1 -1
  121. package/dist/plus/integrations/providers/gitlab/gitlab.d.ts +35 -0
  122. package/dist/plus/integrations/providers/gitlab/gitlab.js +132 -15
  123. package/dist/plus/integrations/providers/gitlab/gitlab.js.map +1 -1
  124. package/dist/plus/integrations/providers/gitlab/models.d.ts +1 -0
  125. package/dist/plus/integrations/providers/gitlab/models.js +1 -1
  126. package/dist/plus/integrations/providers/gitlab/models.js.map +1 -1
  127. package/dist/plus/integrations/providers/gitlab.d.ts +49 -2
  128. package/dist/plus/integrations/providers/gitlab.js +80 -4
  129. package/dist/plus/integrations/providers/gitlab.js.map +1 -1
  130. package/dist/plus/integrations/providers/jira-server.d.ts +3 -3
  131. package/dist/plus/integrations/providers/jira-server.js +5 -8
  132. package/dist/plus/integrations/providers/jira-server.js.map +1 -1
  133. package/dist/plus/integrations/providers/jira.d.ts +9 -0
  134. package/dist/plus/integrations/providers/jira.js +13 -1
  135. package/dist/plus/integrations/providers/jira.js.map +1 -1
  136. package/dist/plus/integrations/providers/linear.js +1 -1
  137. package/dist/plus/integrations/providers/models.d.ts +13 -2
  138. package/dist/plus/integrations/providers/models.js +11 -1
  139. package/dist/plus/integrations/providers/models.js.map +1 -1
  140. package/dist/plus/integrations/providers/providerErrors.d.ts +9 -1
  141. package/dist/plus/integrations/providers/providerErrors.js +10 -1
  142. package/dist/plus/integrations/providers/providerErrors.js.map +1 -1
  143. package/dist/plus/integrations/providers/providersApi.d.ts +60 -1
  144. package/dist/plus/integrations/providers/providersApi.js +137 -2
  145. package/dist/plus/integrations/providers/providersApi.js.map +1 -1
  146. package/dist/plus/integrations/providers/utils/providerPaging.d.ts +42 -0
  147. package/dist/plus/integrations/providers/utils/providerPaging.js +58 -1
  148. package/dist/plus/integrations/providers/utils/providerPaging.js.map +1 -1
  149. package/dist/plus/integrations/providers/utils.d.ts +1 -1
  150. package/dist/plus/integrations/reads/broaden.js +1 -1
  151. package/dist/plus/integrations/reads/context.d.ts +1 -1
  152. package/dist/plus/integrations/reads/counts.js +1 -1
  153. package/dist/plus/integrations/reads/currentAccount.d.ts +35 -0
  154. package/dist/plus/integrations/reads/currentAccount.js +46 -0
  155. package/dist/plus/integrations/reads/currentAccount.js.map +1 -0
  156. package/dist/plus/integrations/reads/drains.d.ts +5 -2
  157. package/dist/plus/integrations/reads/drains.js +8 -4
  158. package/dist/plus/integrations/reads/drains.js.map +1 -1
  159. package/dist/plus/integrations/reads/hierarchy.js +1 -1
  160. package/dist/plus/integrations/reads/hierarchy.utils.js +1 -1
  161. package/dist/plus/integrations/reads/issueBatch.d.ts +72 -12
  162. package/dist/plus/integrations/reads/issueBatch.js +193 -48
  163. package/dist/plus/integrations/reads/issueBatch.js.map +1 -1
  164. package/dist/plus/integrations/reads/issueTracker.js +1 -1
  165. package/dist/plus/integrations/reads/issues.js +1 -1
  166. package/dist/plus/integrations/reads/pullRequestBatch.d.ts +57 -0
  167. package/dist/plus/integrations/reads/pullRequestBatch.js +80 -0
  168. package/dist/plus/integrations/reads/pullRequestBatch.js.map +1 -0
  169. package/dist/plus/integrations/reads/pullRequestBranches.d.ts +58 -0
  170. package/dist/plus/integrations/reads/pullRequestBranches.js +111 -0
  171. package/dist/plus/integrations/reads/pullRequestBranches.js.map +1 -0
  172. package/dist/plus/integrations/reads/pullRequests.js +3 -3
  173. package/dist/plus/integrations/reads/pullRequests.js.map +1 -1
  174. package/dist/plus/integrations/reads/resolveRepository.js +1 -1
  175. package/dist/plus/integrations/reads/sweeps.js +4 -4
  176. package/dist/plus/integrations/reads/sweeps.js.map +1 -1
  177. package/dist/plus/integrations/results.d.ts +87 -6
  178. package/dist/plus/integrations/results.js +9 -2
  179. package/dist/plus/integrations/results.js.map +1 -1
  180. package/dist/utils/env/node/exec.js +3 -3
  181. package/dist/utils/env/node/exec.js.map +1 -1
  182. package/docs/integrations.md +175 -35
  183. package/docs/kepler-git-write-api-parity.md +239 -0
  184. package/docs/kepler-read-api-parity.md +75 -28
  185. package/package.json +1 -1
  186. package/dist/plus/integrations/reads/trackerIssue.d.ts +0 -33
  187. package/dist/plus/integrations/reads/trackerIssue.js +0 -60
  188. package/dist/plus/integrations/reads/trackerIssue.js.map +0 -1
@@ -7,7 +7,7 @@ import { trace } from "../../../utils/decorators/log.js";
7
7
  import { parseUri } from "../../../utils/uri.js";
8
8
  import { createRevisionRange, getRevisionRangeParts, isRevisionRange, isSha, isUncommitted } from "../../../git/utils/revision.utils.js";
9
9
  import __decorate from "../../../_virtual/@oxc-project+runtime/helpers/esm/decorate.js";
10
- import { AuthenticationError, RequestClientError, RequestNotFoundError, RequestRateLimitError } from "../../../git/errors.js";
10
+ import { AuthenticationError, RequestClientError, RequestNotFoundError, RequestRateLimitError, reportRequestFailure } from "../../../git/errors.js";
11
11
  import { Emitter } from "../../../utils/event.js";
12
12
  import { fromString, satisfies } from "../../../utils/version.js";
13
13
  import { maybeStopWatch } from "../../../utils/stopwatch.js";
@@ -302,6 +302,21 @@ repository {
302
302
  url
303
303
  }
304
304
  `;
305
+ /**
306
+ * What an alias's own errors say about its slot in an {@link AliasedGraphqlResult}: `'absent'` only when its node
307
+ * is null and every error on it is NOT_FOUND; a rejection when a node arrived with an error, or on any other error
308
+ * (even a NOT_FOUND nested under the node), since neither is trustworthy; `undefined` when the alias has no errors.
309
+ */
310
+ function getAliasErrorVerdict(errors, alias, node) {
311
+ const aliasErrors = errors.filter((e) => e.path?.[0] === alias);
312
+ if (aliasErrors.length === 0) return void 0;
313
+ if (node == null && aliasErrors.every((e) => e.type === "NOT_FOUND")) return "absent";
314
+ const primary = aliasErrors.find((e) => e.type !== "NOT_FOUND") ?? aliasErrors[0];
315
+ return {
316
+ status: "rejected",
317
+ reason: new Error(primary.message)
318
+ };
319
+ }
305
320
  var GitHubApi = class {
306
321
  config;
307
322
  _onDidReauthenticate = new Emitter();
@@ -1728,7 +1743,7 @@ var GitHubApi = class {
1728
1743
  let dedupeKey;
1729
1744
  if (dedupable) {
1730
1745
  try {
1731
- dedupeKey = `${token.microHash}|${provider?.id ?? ""}|${query}|${JSON.stringify(variables ?? null)}`;
1746
+ dedupeKey = `${token.microHash}|${provider?.id ?? ""}|${allowPartialNotFound ?? ""}|${query}|${JSON.stringify(variables ?? null)}`;
1732
1747
  } catch {
1733
1748
  dedupeKey = void 0;
1734
1749
  }
@@ -1750,10 +1765,19 @@ var GitHubApi = class {
1750
1765
  };
1751
1766
  }
1752
1767
  const retryable = graphqlReadQueryRegex.test(query);
1753
- return await this.requestWithRetries(() => this.config.wrapForForcedInsecureSSL(provider?.getIgnoreSSLErrors() ?? false, () => this.getDefaults(accessToken, graphql)(query, variables)), retryable, cancellation, scope);
1768
+ const data = await this.requestWithRetries(() => this.config.wrapForForcedInsecureSSL(provider?.getIgnoreSSLErrors() ?? false, () => this.getDefaults(accessToken, graphql)(query, variables)), retryable, cancellation, scope);
1769
+ return allowPartialNotFound === "aliased" ? {
1770
+ data,
1771
+ errors: []
1772
+ } : data;
1754
1773
  } catch (ex) {
1755
1774
  if (ex instanceof GraphqlResponseError) {
1756
- if (allowPartialNotFound && ex.data != null && (ex.errors?.every((e) => e.type === "NOT_FOUND") ?? false)) return ex.data;
1775
+ if (allowPartialNotFound === "aliased" && ex.data != null && ex.errors != null && ex.errors.length > 0) {
1776
+ if (ex.errors.every((e) => e.path != null && e.path.length > 0 && e.path[0] in ex.data)) return {
1777
+ data: ex.data,
1778
+ errors: ex.errors
1779
+ };
1780
+ }
1757
1781
  switch (ex.errors?.[0]?.type) {
1758
1782
  case "NOT_FOUND": throw new RequestNotFoundError(ex);
1759
1783
  case "FORBIDDEN": throw new AuthenticationError(tokenInfo, 3, ex);
@@ -1768,7 +1792,7 @@ var GitHubApi = class {
1768
1792
  }
1769
1793
  }
1770
1794
  if (_logger.isDebugging) this.config.onDebugError?.(`GitHub request failed: ${ex.errors?.[0]?.message ?? ex.message}`);
1771
- } else if (ex instanceof RequestError || ex.name === "AbortError") this.handleRequestError(provider, token, ex, scope);
1795
+ } else if (ex instanceof RequestError || ex.name === "AbortError") this.handleRequestError(provider, token, ex, scope, allowPartialNotFound === "aliased");
1772
1796
  else if (_logger.isDebugging) this.config.onDebugError?.(`GitHub request failed: ${ex.message}`);
1773
1797
  throw ex;
1774
1798
  }
@@ -1812,7 +1836,7 @@ var GitHubApi = class {
1812
1836
  const retryable = method === "GET" || method === "HEAD";
1813
1837
  return await this.requestWithRetries(() => this.config.wrapForForcedInsecureSSL(provider?.getIgnoreSSLErrors() ?? false, () => this.getDefaults(accessToken, request)(route, options)), retryable, signal, scope);
1814
1838
  } catch (ex) {
1815
- if (ex instanceof RequestError || ex.name === "AbortError") this.handleRequestError(provider, token, ex, scope);
1839
+ if (ex instanceof RequestError || ex.name === "AbortError") this.handleRequestError(provider, token, ex, scope, void 0);
1816
1840
  else if (_logger.isDebugging) this.config.onDebugError?.(`GitHub request failed: ${ex.message}`);
1817
1841
  throw ex;
1818
1842
  }
@@ -1856,7 +1880,7 @@ var GitHubApi = class {
1856
1880
  }
1857
1881
  return defaults;
1858
1882
  }
1859
- handleRequestError(provider, token, ex, scope) {
1883
+ handleRequestError(provider, token, ex, scope, deferFailure) {
1860
1884
  if (ex.name === "AbortError") throw new CancellationError(ex);
1861
1885
  const { accessToken, ...tokenInfo } = token;
1862
1886
  switch (ex.status) {
@@ -1870,23 +1894,18 @@ var GitHubApi = class {
1870
1894
  throw new AuthenticationError(tokenInfo, 3, ex);
1871
1895
  case 500:
1872
1896
  scope?.error(ex);
1873
- if (ex.response != null) {
1874
- provider?.trackRequestException();
1875
- this.config.onRequestError?.(provider, provider == null || provider.id === "github" ? l10n.t("{0} failed to respond and might be experiencing issues. Please visit the [GitHub status page](https://githubstatus.com) for more information.", provider?.name ?? "GitHub") : l10n.t("{0} failed to respond and might be experiencing issues.", provider.name));
1876
- }
1897
+ if (ex.response != null) reportRequestFailure(provider, ex, () => this.config.onRequestError?.(provider, provider == null || provider.id === "github" ? l10n.t("{0} failed to respond and might be experiencing issues. Please visit the [GitHub status page](https://githubstatus.com) for more information.", provider?.name ?? "GitHub") : l10n.t("{0} failed to respond and might be experiencing issues.", provider.name)), deferFailure);
1877
1898
  return;
1878
1899
  case 502:
1879
1900
  scope?.error(ex);
1880
1901
  if (ex.message.includes("timeout")) {
1881
- provider?.trackRequestException();
1882
- this.config.onRequestError?.(provider, `${provider?.name ?? "GitHub"} request timed out`);
1902
+ reportRequestFailure(provider, ex, () => this.config.onRequestError?.(provider, `${provider?.name ?? "GitHub"} request timed out`), deferFailure);
1883
1903
  return;
1884
1904
  }
1885
1905
  break;
1886
1906
  case 503:
1887
1907
  scope?.error(ex);
1888
- provider?.trackRequestException();
1889
- this.config.onRequestError?.(provider, provider == null || provider.id === "github" ? l10n.t("{0} failed to respond and might be experiencing issues. Please visit the [GitHub status page](https://githubstatus.com) for more information.", provider?.name ?? "GitHub") : l10n.t("{0} failed to respond and might be experiencing issues.", provider.name));
1908
+ reportRequestFailure(provider, ex, () => this.config.onRequestError?.(provider, provider == null || provider.id === "github" ? l10n.t("{0} failed to respond and might be experiencing issues. Please visit the [GitHub status page](https://githubstatus.com) for more information.", provider?.name ?? "GitHub") : l10n.t("{0} failed to respond and might be experiencing issues.", provider.name)), deferFailure);
1890
1909
  return;
1891
1910
  default: if (ex.status >= 400 && ex.status < 500) throw new RequestClientError(ex);
1892
1911
  }
@@ -2206,8 +2225,10 @@ var GitHubApi = class {
2206
2225
  *
2207
2226
  * Returns POSITIONALLY — one slot per input coordinate, in order — for the same reason {@link countIssues}
2208
2227
  * does: a caller's key is arbitrary text and would break the GraphQL document, so the aliases are generated
2209
- * and the caller maps back by index. `undefined` in a slot means the issue does not exist (or is not visible
2210
- * to this token), never that the read failed; a failure throws.
2228
+ * and the caller maps back by index. A `fulfilled` slot with `undefined` means the issue does not exist (or
2229
+ * is not visible to this token) — a PROVEN ABSENCE. A `rejected` slot means only THAT target failed — e.g. an
2230
+ * org enforcing SAML SSO the token isn't authorized for — which is not proof the issue is gone, so it must
2231
+ * not be cached as absent. A whole-request failure (bad credentials, rate limit, no data at all) still throws.
2211
2232
  */
2212
2233
  async getIssuesBatch(provider, token, coordinates, options, cancellation) {
2213
2234
  const scope = getScopedLogger();
@@ -2232,16 +2253,200 @@ var GitHubApi = class {
2232
2253
  variables[`k${i}`] = c.number;
2233
2254
  });
2234
2255
  try {
2235
- const rsp = await this.graphql(provider, token, query, variables, scope, cancellation, true);
2236
- if (rsp == null) return coordinates.map(() => void 0);
2256
+ const rsp = await this.graphql(provider, token, query, variables, scope, cancellation, "aliased");
2257
+ if (rsp?.data == null) throw new Error("GitHub returned no data for the issue batch");
2237
2258
  return coordinates.map((c, i) => {
2238
- const node = rsp[`i${i}`]?.issue;
2239
- if (node == null) return void 0;
2259
+ const alias = `i${i}`;
2260
+ const node = rsp.data[alias]?.issue;
2261
+ const verdict = getAliasErrorVerdict(rsp.errors, alias, node);
2262
+ if (verdict === "absent") return {
2263
+ status: "fulfilled",
2264
+ value: void 0
2265
+ };
2266
+ if (verdict != null) return verdict;
2267
+ if (node == null) return {
2268
+ status: "fulfilled",
2269
+ value: void 0
2270
+ };
2240
2271
  try {
2241
- return fromGitHubIssue(node, provider);
2272
+ return {
2273
+ status: "fulfilled",
2274
+ value: fromGitHubIssue(node, provider)
2275
+ };
2242
2276
  } catch (ex) {
2243
- scope?.warn(`skipped unmappable issue; ${c.owner}/${c.repo}#${c.number}, ex=${ex}`);
2244
- return;
2277
+ scope?.warn(`failed to map issue; ${c.owner}/${c.repo}#${c.number}, ex=${ex}`);
2278
+ return {
2279
+ status: "rejected",
2280
+ reason: ex
2281
+ };
2282
+ }
2283
+ });
2284
+ } catch (ex) {
2285
+ throw this.handleException(ex, provider, scope);
2286
+ }
2287
+ }
2288
+ /**
2289
+ * Resolves several pull requests, in any state (open/closed/merged), BY COORDINATE — `(owner, repo, number)`
2290
+ * — in one request, via aliased `repository` fields rather than aliased searches. The pull-request twin of
2291
+ * {@link getIssuesBatch}; see that method for why aliasing the point read (exact number, no result ceiling,
2292
+ * a proven absence) is the design.
2293
+ *
2294
+ * Selects the FULL {@link gqlPullRequestFragment} — not the lite shape {@link getPullRequest} uses — so a
2295
+ * row from this read carries the same fields (reviews, review requests, checks, diff stats, assignees,
2296
+ * mergeable state) as {@link searchMyPullRequestsPage}'s account-wide rows.
2297
+ *
2298
+ * Returns POSITIONALLY — one slot per input coordinate, in order — for the same reason {@link getIssuesBatch}
2299
+ * does: a caller's key is arbitrary text and would break the GraphQL document, so the aliases are generated
2300
+ * and the caller maps back by index. A `fulfilled` slot with `undefined` means the pull request (or its
2301
+ * repository) does not exist or is not visible to this token — a PROVEN ABSENCE. A `rejected` slot means only
2302
+ * THAT target failed — e.g. an org enforcing SAML SSO the token isn't authorized for — which is not proof the
2303
+ * pull request is gone, so it must not be cached as absent. A whole-request failure still throws.
2304
+ */
2305
+ async getPullRequestsBatch(provider, token, coordinates, options, cancellation) {
2306
+ const scope = getScopedLogger();
2307
+ if (coordinates.length === 0) return [];
2308
+ const query = `query getPullRequestsBatch(
2309
+ ${coordinates.map((_, i) => `$o${i}: String!\n\t\t\t\t$n${i}: String!\n\t\t\t\t$k${i}: Int!`).join("\n ")}
2310
+ $avatarSize: Int
2311
+ ) {
2312
+ ${coordinates.map((_, i) => `p${i}: repository(owner: $o${i}, name: $n${i}) {
2313
+ pullRequest(number: $k${i}) {
2314
+ ${gqlPullRequestFragment}
2315
+ ${gqlPullRequestStackFragmentFor(options)}
2316
+ }
2317
+ }`).join("\n ")}
2318
+ }`;
2319
+ const variables = {
2320
+ baseUrl: options?.baseUrl,
2321
+ avatarSize: options?.avatarSize
2322
+ };
2323
+ coordinates.forEach((c, i) => {
2324
+ variables[`o${i}`] = c.owner;
2325
+ variables[`n${i}`] = c.repo;
2326
+ variables[`k${i}`] = c.number;
2327
+ });
2328
+ try {
2329
+ const rsp = await this.graphql(provider, token, query, variables, scope, cancellation, "aliased");
2330
+ if (rsp?.data == null) throw new Error("GitHub returned no data for the pull request batch");
2331
+ return coordinates.map((c, i) => {
2332
+ const alias = `p${i}`;
2333
+ const node = rsp.data[alias]?.pullRequest;
2334
+ const verdict = getAliasErrorVerdict(rsp.errors, alias, node);
2335
+ if (verdict === "absent") return {
2336
+ status: "fulfilled",
2337
+ value: void 0
2338
+ };
2339
+ if (verdict != null) return verdict;
2340
+ if (node == null) return {
2341
+ status: "fulfilled",
2342
+ value: void 0
2343
+ };
2344
+ try {
2345
+ return {
2346
+ status: "fulfilled",
2347
+ value: fromGitHubPullRequest(node, provider)
2348
+ };
2349
+ } catch (ex) {
2350
+ scope?.warn(`failed to map pull request; ${c.owner}/${c.repo}#${c.number}, ex=${ex}`);
2351
+ return {
2352
+ status: "rejected",
2353
+ reason: ex
2354
+ };
2355
+ }
2356
+ });
2357
+ } catch (ex) {
2358
+ throw this.handleException(ex, provider, scope);
2359
+ }
2360
+ }
2361
+ /**
2362
+ * Finds, for several branches in one request, every pull request whose head is that branch — in any state,
2363
+ * most recently updated first, up to `limit` per branch. Each target names the BASE repository the pull
2364
+ * requests are opened against, the head branch's short name and, for a branch that lives in a fork,
2365
+ * `headOwner`, the fork's owner.
2366
+ *
2367
+ * Keyed on the head ref NAME (`repository.pullRequests(headRefName:)`) rather than on the ref itself
2368
+ * (`repository.ref(qualifiedName:).associatedPullRequests`, which {@link getPullRequestForBranch} uses): a
2369
+ * merged pull request's branch is usually deleted afterwards, and the ref lookup then answers "none" for a
2370
+ * pull request that exists.
2371
+ *
2372
+ * `headRefName` matches every fork's branch of that name too, so rows are kept only when their head
2373
+ * repository is the base repository itself (`headOwner` omitted) or a fork owned by `headOwner` — otherwise
2374
+ * a `main` in the base repository would claim every fork's `main`. That filter runs after the server's
2375
+ * `limit`, so `truncated` is set whenever the server matched more rows than it returned, since any of the
2376
+ * unfetched ones might have passed it.
2377
+ *
2378
+ * Returns POSITIONALLY, with the same per-alias rules as {@link getPullRequestsBatch}: a missing base
2379
+ * repository (NOT_FOUND on a null repository) is a PROVEN "none" — an empty list — while any other error on
2380
+ * a target's alias rejects only that target, and a whole-request failure still throws.
2381
+ */
2382
+ async getPullRequestsForBranches(provider, token, targets, options, cancellation) {
2383
+ const scope = getScopedLogger();
2384
+ if (targets.length === 0) return [];
2385
+ const query = `query getPullRequestsForBranches(
2386
+ ${targets.map((_, i) => `$o${i}: String!\n\t\t\t\t$n${i}: String!\n\t\t\t\t$h${i}: String!`).join("\n ")}
2387
+ $limit: Int!
2388
+ $avatarSize: Int
2389
+ ) {
2390
+ ${targets.map((_, i) => `b${i}: repository(owner: $o${i}, name: $n${i}) {
2391
+ pullRequests(headRefName: $h${i}, states: [OPEN, CLOSED, MERGED], first: $limit, orderBy: {field: UPDATED_AT, direction: DESC}) {
2392
+ totalCount
2393
+ nodes {
2394
+ ${gqlPullRequestFragment}
2395
+ ${gqlPullRequestStackFragmentFor(options)}
2396
+ headRepositoryOwner {
2397
+ login
2398
+ }
2399
+ }
2400
+ }
2401
+ }`).join("\n ")}
2402
+ }`;
2403
+ const variables = {
2404
+ baseUrl: options.baseUrl,
2405
+ avatarSize: options.avatarSize,
2406
+ limit: options.limit
2407
+ };
2408
+ targets.forEach((t, i) => {
2409
+ variables[`o${i}`] = t.owner;
2410
+ variables[`n${i}`] = t.repo;
2411
+ variables[`h${i}`] = t.branch;
2412
+ });
2413
+ try {
2414
+ const rsp = await this.graphql(provider, token, query, variables, scope, cancellation, "aliased");
2415
+ if (rsp?.data == null) throw new Error("GitHub returned no data for the pull requests by branch");
2416
+ return targets.map((t, i) => {
2417
+ const alias = `b${i}`;
2418
+ const repository = rsp.data[alias];
2419
+ const verdict = getAliasErrorVerdict(rsp.errors, alias, repository);
2420
+ if (verdict != null && verdict !== "absent") return verdict;
2421
+ if (repository == null) return {
2422
+ status: "fulfilled",
2423
+ value: {
2424
+ pullRequests: [],
2425
+ truncated: false
2426
+ }
2427
+ };
2428
+ const connection = repository.pullRequests;
2429
+ if (connection == null) return {
2430
+ status: "rejected",
2431
+ reason: /* @__PURE__ */ new Error(`GitHub returned no pull requests for ${t.owner}/${t.repo}:${t.branch}`)
2432
+ };
2433
+ const headOwner = t.headOwner?.toLowerCase();
2434
+ const nodes = connection.nodes.filter((pr) => pr != null);
2435
+ const matches = nodes.filter((pr) => pr.headRefName === t.branch && (headOwner == null ? !pr.isCrossRepository : pr.isCrossRepository && pr.headRepositoryOwner?.login.toLowerCase() === headOwner));
2436
+ try {
2437
+ return {
2438
+ status: "fulfilled",
2439
+ value: {
2440
+ pullRequests: matches.map((pr) => fromGitHubPullRequest(pr, provider)).sort((a, b) => b.updatedDate.getTime() - a.updatedDate.getTime()),
2441
+ truncated: connection.totalCount > nodes.length
2442
+ }
2443
+ };
2444
+ } catch (ex) {
2445
+ scope?.warn(`failed to map pull requests; ${t.owner}/${t.repo}:${t.branch}, ex=${ex}`);
2446
+ return {
2447
+ status: "rejected",
2448
+ reason: ex
2449
+ };
2245
2450
  }
2246
2451
  });
2247
2452
  } catch (ex) {
@@ -3016,6 +3221,14 @@ __decorate([trace({ args: (provider, token) => ({
3016
3221
  provider: provider.name,
3017
3222
  token: `<token:${token.microHash}>`
3018
3223
  }) })], GitHubApi.prototype, "getIssuesBatch", null);
3224
+ __decorate([trace({ args: (provider, token) => ({
3225
+ provider: provider.name,
3226
+ token: `<token:${token.microHash}>`
3227
+ }) })], GitHubApi.prototype, "getPullRequestsBatch", null);
3228
+ __decorate([trace({ args: (provider, token) => ({
3229
+ provider: provider.name,
3230
+ token: `<token:${token.microHash}>`
3231
+ }) })], GitHubApi.prototype, "getPullRequestsForBranches", null);
3019
3232
  __decorate([trace({ args: (provider, token) => ({
3020
3233
  provider: provider.name,
3021
3234
  token: `<token:${token.microHash}>`