@gitkraken/core-gitlens 0.13.0 → 0.15.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 (127) hide show
  1. package/CHANGELOG.md +43 -2
  2. package/dist/git/features.d.ts +1 -1
  3. package/dist/git/features.js +1 -0
  4. package/dist/git/features.js.map +1 -1
  5. package/dist/git/models/branch.d.ts +5 -0
  6. package/dist/git/models/branch.js +1 -1
  7. package/dist/git/models/branch.js.map +1 -1
  8. package/dist/git/models/reference.d.ts +3 -0
  9. package/dist/git/models/status.js +1 -1
  10. package/dist/git/parsers/diffParser.js +1 -1
  11. package/dist/git/providers/operations.d.ts +3 -2
  12. package/dist/git/providers/provider.d.ts +15 -4
  13. package/dist/git/providers/revision.d.ts +17 -3
  14. package/dist/git/run.types.d.ts +12 -0
  15. package/dist/git/utils/branch.utils.d.ts +4 -1
  16. package/dist/git/utils/branch.utils.js +20 -5
  17. package/dist/git/utils/branch.utils.js.map +1 -1
  18. package/dist/git/utils/reference.utils.d.ts +1 -0
  19. package/dist/git/utils/reference.utils.js.map +1 -1
  20. package/dist/git-cli/cliGitProvider.d.ts +8 -2
  21. package/dist/git-cli/cliGitProvider.js +75 -13
  22. package/dist/git-cli/cliGitProvider.js.map +1 -1
  23. package/dist/git-cli/exec/git.d.ts +5 -0
  24. package/dist/git-cli/exec/git.js +28 -5
  25. package/dist/git-cli/exec/git.js.map +1 -1
  26. package/dist/git-cli/exec/indexLock.d.ts +3 -2
  27. package/dist/git-cli/exec/indexLock.js +16 -6
  28. package/dist/git-cli/exec/indexLock.js.map +1 -1
  29. package/dist/git-cli/parsers/blameParser.js +2 -2
  30. package/dist/git-cli/parsers/refParser.js +4 -2
  31. package/dist/git-cli/parsers/refParser.js.map +1 -1
  32. package/dist/git-cli/parsers/statusParser.d.ts +6 -0
  33. package/dist/git-cli/parsers/statusParser.js +33 -3
  34. package/dist/git-cli/parsers/statusParser.js.map +1 -1
  35. package/dist/git-cli/providers/branchRemote.d.ts +14 -0
  36. package/dist/git-cli/providers/branchRemote.js +36 -0
  37. package/dist/git-cli/providers/branchRemote.js.map +1 -0
  38. package/dist/git-cli/providers/branches.js +6 -3
  39. package/dist/git-cli/providers/branches.js.map +1 -1
  40. package/dist/git-cli/providers/commits.js +2 -2
  41. package/dist/git-cli/providers/config.js +2 -2
  42. package/dist/git-cli/providers/contributors.js +1 -1
  43. package/dist/git-cli/providers/graph.js +9 -6
  44. package/dist/git-cli/providers/graph.js.map +1 -1
  45. package/dist/git-cli/providers/operations.js +20 -16
  46. package/dist/git-cli/providers/operations.js.map +1 -1
  47. package/dist/git-cli/providers/pausedOperations.js +2 -2
  48. package/dist/git-cli/providers/pausedOperations.js.map +1 -1
  49. package/dist/git-cli/providers/revision.d.ts +6 -2
  50. package/dist/git-cli/providers/revision.js +38 -12
  51. package/dist/git-cli/providers/revision.js.map +1 -1
  52. package/dist/git-cli/providers/staging.js +1 -1
  53. package/dist/git-cli/providers/status.js +2 -2
  54. package/dist/ipc/discovery.js +1 -1
  55. package/dist/plus/agents/providers/claudeCodeTranscript.js +6 -6
  56. package/dist/plus/agents/providers/claudeCodeTranscript.js.map +1 -1
  57. package/dist/plus/ai/providers/openAICompatibleProviderBase.js +1 -1
  58. package/dist/plus/git-github/providers/github/revision.d.ts +6 -2
  59. package/dist/plus/git-github/providers/github/revision.js +15 -10
  60. package/dist/plus/git-github/providers/github/revision.js.map +1 -1
  61. package/dist/plus/git-github/providers/github/status.js +1 -1
  62. package/dist/plus/integrations/collectionMetadata.d.ts +7 -0
  63. package/dist/plus/integrations/collectionMetadata.js +10 -1
  64. package/dist/plus/integrations/collectionMetadata.js.map +1 -1
  65. package/dist/plus/integrations/errors.d.ts +5 -0
  66. package/dist/plus/integrations/errors.js +10 -1
  67. package/dist/plus/integrations/errors.js.map +1 -1
  68. package/dist/plus/integrations/index.d.ts +2 -2
  69. package/dist/plus/integrations/index.js.map +1 -1
  70. package/dist/plus/integrations/models/gitHostIntegration.d.ts +6 -2
  71. package/dist/plus/integrations/models/gitHostIntegration.js +37 -7
  72. package/dist/plus/integrations/models/gitHostIntegration.js.map +1 -1
  73. package/dist/plus/integrations/models/issueReads.d.ts +1 -1
  74. package/dist/plus/integrations/models/issuesIntegration.d.ts +33 -3
  75. package/dist/plus/integrations/models/issuesIntegration.js +76 -5
  76. package/dist/plus/integrations/models/issuesIntegration.js.map +1 -1
  77. package/dist/plus/integrations/providers/azure/azure.js +1 -1
  78. package/dist/plus/integrations/providers/azure/workItemStateCategories.d.ts +5 -0
  79. package/dist/plus/integrations/providers/azure/workItemStateCategories.js +5 -0
  80. package/dist/plus/integrations/providers/azure/workItemStateCategories.js.map +1 -1
  81. package/dist/plus/integrations/providers/azureDevOpsServer.d.ts +9 -1
  82. package/dist/plus/integrations/providers/azureDevOpsServer.js +17 -9
  83. package/dist/plus/integrations/providers/azureDevOpsServer.js.map +1 -1
  84. package/dist/plus/integrations/providers/bitbucket-server.js +3 -2
  85. package/dist/plus/integrations/providers/bitbucket-server.js.map +1 -1
  86. package/dist/plus/integrations/providers/jira-server.d.ts +3 -0
  87. package/dist/plus/integrations/providers/jira-server.js +15 -7
  88. package/dist/plus/integrations/providers/jira-server.js.map +1 -1
  89. package/dist/plus/integrations/providers/jira.d.ts +8 -0
  90. package/dist/plus/integrations/providers/jira.js +88 -58
  91. package/dist/plus/integrations/providers/jira.js.map +1 -1
  92. package/dist/plus/integrations/providers/linear.d.ts +4 -0
  93. package/dist/plus/integrations/providers/linear.js +23 -2
  94. package/dist/plus/integrations/providers/linear.js.map +1 -1
  95. package/dist/plus/integrations/providers/providerErrors.d.ts +24 -0
  96. package/dist/plus/integrations/providers/providerErrors.js +41 -4
  97. package/dist/plus/integrations/providers/providerErrors.js.map +1 -1
  98. package/dist/plus/integrations/providers/providersApi.d.ts +1 -1
  99. package/dist/plus/integrations/providers/providersApi.js +15 -4
  100. package/dist/plus/integrations/providers/providersApi.js.map +1 -1
  101. package/dist/plus/integrations/providers/trello.d.ts +1 -0
  102. package/dist/plus/integrations/providers/trello.js +3 -0
  103. package/dist/plus/integrations/providers/trello.js.map +1 -1
  104. package/dist/plus/integrations/reads/cursors.js +23 -5
  105. package/dist/plus/integrations/reads/cursors.js.map +1 -1
  106. package/dist/plus/integrations/reads/drains.d.ts +16 -0
  107. package/dist/plus/integrations/reads/drains.js +19 -1
  108. package/dist/plus/integrations/reads/drains.js.map +1 -1
  109. package/dist/plus/integrations/reads/hierarchy.js +5 -3
  110. package/dist/plus/integrations/reads/hierarchy.js.map +1 -1
  111. package/dist/plus/integrations/reads/hierarchy.utils.d.ts +3 -2
  112. package/dist/plus/integrations/reads/hierarchy.utils.js +4 -7
  113. package/dist/plus/integrations/reads/hierarchy.utils.js.map +1 -1
  114. package/dist/plus/integrations/reads/issueTracker.js +71 -7
  115. package/dist/plus/integrations/reads/issueTracker.js.map +1 -1
  116. package/dist/plus/integrations/reads/selectionConfirmation.d.ts +69 -0
  117. package/dist/plus/integrations/reads/selectionConfirmation.js +79 -0
  118. package/dist/plus/integrations/reads/selectionConfirmation.js.map +1 -0
  119. package/dist/plus/integrations/reads/warnings.d.ts +9 -3
  120. package/dist/plus/integrations/reads/warnings.js +19 -3
  121. package/dist/plus/integrations/reads/warnings.js.map +1 -1
  122. package/dist/plus/integrations/results.d.ts +30 -3
  123. package/dist/plus/integrations/results.js +2 -1
  124. package/dist/plus/integrations/results.js.map +1 -1
  125. package/dist/utils/env/node/exec.js +2 -2
  126. package/docs/integrations.md +59 -6
  127. package/package.json +1 -1
@@ -150,6 +150,15 @@ function getResponseHeader(headers, name) {
150
150
  return typeof headers.get === "function" ? headers.get(name) : headers[name];
151
151
  }
152
152
  /**
153
+ * The user a Jira or Bitbucket Data Center response names in `X-AUSERNAME`: the user the request authenticated as,
154
+ * `anonymous` when its credential did not authenticate, or none (`undefined`) when the response carries no name.
155
+ */
156
+ function getAuthenticatedUser(headers) {
157
+ const user = getResponseHeader(headers, "x-ausername");
158
+ if (typeof user !== "string" || user === "") return void 0;
159
+ return user.toLowerCase() === "anonymous" ? "anonymous" : user;
160
+ }
161
+ /**
153
162
  * Builds a {@link RequestRateLimitError} from a provider error response, reading the reset epoch from the
154
163
  * standard `x-ratelimit-reset` header when present. Accepts both header shapes in use: the `fetch` `Headers`
155
164
  * instance the direct clients get, and the plain object the SDK attaches to its errors.
@@ -173,6 +182,6 @@ function toError(ex) {
173
182
  return ex instanceof Error ? ex : new Error(String(ex));
174
183
  }
175
184
  //#endregion
176
- export { AuthenticationError, AuthenticationErrorReason, IntegrationReadUnavailableError, ProviderFetchError, RequestClientError, RequestNotFoundError, RequestRateLimitError, getResponseHeader, isProviderUnreachableError, isRateLimitResponse, toError, toRateLimitError };
185
+ export { AuthenticationError, AuthenticationErrorReason, IntegrationReadUnavailableError, ProviderFetchError, RequestClientError, RequestNotFoundError, RequestRateLimitError, getAuthenticatedUser, getResponseHeader, isProviderUnreachableError, isRateLimitResponse, toError, toRateLimitError };
177
186
 
178
187
  //# sourceMappingURL=errors.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","names":[],"sources":["../../../../plus/integrations/src/errors.ts"],"sourcesContent":["export type { AuthTokenInfo } from '@gitlens/git/errors.js';\nexport {\n\tAuthenticationError,\n\tAuthenticationErrorReason,\n\tRequestClientError,\n\tRequestNotFoundError,\n\tRequestRateLimitError,\n} from '@gitlens/git/errors.js';\n\nimport { RequestRateLimitError } from '@gitlens/git/errors.js';\nimport { isCancellationError } from '@gitlens/utils/cancellation.js';\n\nconst unreachableErrorCodes = new Set([\n\t'ECONNREFUSED',\n\t'ECONNRESET',\n\t'ECONNABORTED',\n\t'ENOTFOUND',\n\t'EAI_AGAIN',\n\t'ETIMEDOUT',\n\t'EHOSTUNREACH',\n\t'ENETUNREACH',\n\t'EPIPE',\n\t'ERR_NETWORK',\n\t'UND_ERR_CONNECT_TIMEOUT',\n\t'UND_ERR_HEADERS_TIMEOUT',\n\t'UND_ERR_BODY_TIMEOUT',\n\t'UND_ERR_SOCKET',\n\t'CERT_HAS_EXPIRED',\n\t'DEPTH_ZERO_SELF_SIGNED_CERT',\n\t'SELF_SIGNED_CERT_IN_CHAIN',\n\t'UNABLE_TO_VERIFY_LEAF_SIGNATURE',\n\t'UNABLE_TO_GET_ISSUER_CERT_LOCALLY',\n\t'ERR_TLS_CERT_ALTNAME_INVALID',\n]);\n\n/** Transport wrappers keep the network failure in `cause` or `original`; inspecting only the wrapper loses it. */\nexport function isProviderUnreachableError(ex: unknown): boolean {\n\tconst pending = [ex];\n\tconst seen = new Set<unknown>();\n\twhile (pending.length > 0) {\n\t\tconst candidate = pending.pop();\n\t\tif (candidate == null || typeof candidate !== 'object' || seen.has(candidate)) continue;\n\n\t\tseen.add(candidate);\n\t\tconst error = candidate as {\n\t\t\tname?: string;\n\t\t\tkind?: string;\n\t\t\tmessage?: string;\n\t\t\tcode?: string;\n\t\t\tstatus?: number;\n\t\t\tresponse?: { status?: number };\n\t\t\treason?: string;\n\t\t\toriginal?: unknown;\n\t\t\tcause?: unknown;\n\t\t\terrors?: unknown[];\n\t\t};\n\t\tif (isCancellationError(candidate)) {\n\t\t\tif (error.reason === 'aborted') return false;\n\t\t\tif (error.reason === 'timeout') return true;\n\t\t}\n\n\t\tconst status = error.status ?? error.response?.status;\n\t\tif (typeof status === 'number' && status >= 400) return status >= 500 && status < 600;\n\n\t\tif (\n\t\t\terror.kind === 'network' ||\n\t\t\terror.reason === 'unreachable' ||\n\t\t\terror.name === 'TimeoutError' ||\n\t\t\terror.name === 'AbortError' ||\n\t\t\terror.name === 'NetworkError' ||\n\t\t\t(typeof error.code === 'string' &&\n\t\t\t\t(unreachableErrorCodes.has(error.code) || error.code.startsWith('ERR_SSL_'))) ||\n\t\t\t(typeof error.message === 'string' &&\n\t\t\t\t/^(?:fetch failed|failed to fetch|network request failed|load failed|NetworkError when attempting to fetch resource\\.?)$/i.test(\n\t\t\t\t\terror.message,\n\t\t\t\t))\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\n\t\tpending.push(error.original, error.cause);\n\t\tif (Array.isArray(error.errors)) {\n\t\t\tpending.push(...error.errors);\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Thrown by a provider read when it can't produce a result for a reason that is NOT \"the account is empty\":\n * a prerequisite is missing (e.g. Trello has no app key) or a required scope can't be resolved (e.g. the\n * Linear viewer id, needed to scope \"my issues\"). Returning an empty/undefined result in these cases would be\n * indistinguishable from a genuinely empty account; throwing this lets the result cores recover it into an\n * `{ error }` the facade surfaces as a warning + `fetchFailed`.\n */\nexport class IntegrationReadUnavailableError extends Error {\n\tconstructor(provider: string, reason: string) {\n\t\tsuper(`${provider} read unavailable: ${reason}`);\n\t\tError.captureStackTrace?.(this, new.target);\n\t}\n}\n\n/**\n * Thrown by integration provider HTTP clients when an upstream request fails.\n */\nexport class ProviderFetchError extends Error {\n\tget status(): number {\n\t\treturn this.response.status;\n\t}\n\n\tget statusText(): string {\n\t\treturn this.response.statusText;\n\t}\n\n\t/**\n\t * Builds the error with the upstream body folded into the message, for clients that hold a `Response` whose\n\t * body has not been read (i.e. every non-`ok` path). Use this rather than the constructor whenever the body is\n\t * still available: the status line alone cannot distinguish a throttled request from a permission failure on\n\t * the statuses hosts overload (see {@link isRateLimitResponse}), and only the body says which one it is.\n\t *\n\t * Never throws: the body is best-effort, so an unreadable, empty, or already-consumed one simply yields the\n\t * status-line-only message the constructor would have produced.\n\t */\n\tstatic async fromResponse(provider: string, response: Response): Promise<ProviderFetchError> {\n\t\treturn new ProviderFetchError(provider, response, await readErrorBodyMessage(response));\n\t}\n\n\tconstructor(\n\t\tprovider: string,\n\t\tpublic readonly response: Response,\n\t\terrors?: { message: string }[],\n\t) {\n\t\tsuper(\n\t\t\t`${provider} request failed: ${!response.ok ? `(${response.status}) ${response.statusText}. ` : ''}${\n\t\t\t\terrors?.length ? errors[0].message : ''\n\t\t\t}`,\n\t\t);\n\n\t\tError.captureStackTrace?.(this, new.target);\n\t}\n}\n\n/** Cap on the body text folded into an error message, so an HTML error page can't become the message. */\nconst maxErrorBodyLength = 500;\n\n/**\n * Best-effort human-readable message from an error response body, in the `errors` shape the\n * {@link ProviderFetchError} constructor takes. Tolerant by design — every host in use words its errors\n * differently and some do not send JSON at all:\n * - Azure DevOps — `{ message: \"TF400733: ...\" }`\n * - Bitbucket — `{ error: { message: \"...\" } }`, and bare text for a throttled request\n * - GitLab — `{ message: \"...\" }` or `{ error: \"...\" }`\n * Anything unrecognized falls back to the raw text, which is what the substring check wants anyway.\n */\nasync function readErrorBodyMessage(response: Response): Promise<{ message: string }[] | undefined> {\n\tlet text;\n\ttry {\n\t\t// `bodyUsed` is not a guarantee (a stream can fail mid-read), hence the catch — but it avoids the throw\n\t\t// entirely on the common path where something upstream already consumed the body.\n\t\tif (response.bodyUsed) return undefined;\n\n\t\ttext = (await response.text())?.trim();\n\t} catch {\n\t\treturn undefined;\n\t}\n\tif (!text) return undefined;\n\n\tlet message: string | undefined;\n\ttry {\n\t\tconst body: unknown = JSON.parse(text);\n\t\tif (body != null && typeof body === 'object') {\n\t\t\tconst { message: m, error } = body as { message?: unknown; error?: unknown };\n\t\t\tif (typeof m === 'string') {\n\t\t\t\tmessage = m;\n\t\t\t} else if (typeof error === 'string') {\n\t\t\t\tmessage = error;\n\t\t\t} else if (error != null && typeof error === 'object') {\n\t\t\t\t// Some hosts nest it as `{ error: { message } }`; narrow the same way as the outer object.\n\t\t\t\tconst nested = (error as { message?: unknown }).message;\n\t\t\t\tif (typeof nested === 'string') {\n\t\t\t\t\tmessage = nested;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Not JSON — Bitbucket sends bare text for a throttled request, and any host can send an HTML error page.\n\t}\n\n\tmessage = (message ?? text).trim();\n\treturn message ? [{ message: message.slice(0, maxErrorBodyLength) }] : undefined;\n}\n\n/**\n * Whether a provider's error response denotes a rate limit rather than a permission failure. Kept here, in one\n * place, because the distinction is consequential: a rate limit is retryable, while a permission failure is\n * surfaced as `auth` and drives a reconnect prompt — misclassifying one as the other asks the user to\n * re-authenticate a perfectly healthy connection.\n *\n * Which status a throttled request arrives on varies by host, which is why this takes both:\n * - Azure DevOps and Bitbucket Cloud document 429 (learn.microsoft.com .../integrate/concepts/rate-limits).\n * - GitHub documents \"a `403` or `429` response\" for both its primary and secondary limits\n * (docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api).\n * - GitLab uses 403 for some throttles.\n * So 429 alone is decisive, and on 403 the message decides.\n *\n * NOTE the message must actually carry the host's body for the 403 path to work — see\n * {@link ProviderFetchError.fromResponse}. A `ProviderFetchError` built from the status line alone reads\n * \"(403) Forbidden.\" and can never match, which is what made this check dead code on the direct-fetch clients.\n */\nexport function isRateLimitResponse(ex: { status: number; message?: string }): boolean {\n\t// Matches the phrasing hosts actually use: GitHub/Bitbucket \"API rate limit exceeded\", GitLab \"rate limit\n\t// exceeded\", Azure \"Request was blocked due to exceeding usage of resource 'RateLimit'\" / \"TF400733: The\n\t// request has been canceled: Request was blocked due to exceeding usage\".\n\tif (ex.status === 429) return true;\n\n\tconst message = ex.message?.toLowerCase();\n\treturn message != null && (message.includes('rate limit') || message.includes('ratelimit'));\n}\n\n/**\n * A response's headers as either a `fetch` `Headers` instance or the plain object an SDK error carries. Read via\n * duck-typing on `get` rather than `instanceof Headers`, so this works in both the Node and webworker builds\n * without depending on the global being present.\n */\nexport type ResponseHeaders = Pick<Headers, 'get'> | Record<string, unknown>;\n\n/** Reads one header off either shape of {@link ResponseHeaders}; names are the lower-case ones both shapes use. */\nexport function getResponseHeader(headers: ResponseHeaders | undefined, name: string): unknown {\n\tif (headers == null) return undefined;\n\n\treturn typeof headers.get === 'function'\n\t\t? (headers.get as (name: string) => string | null)(name)\n\t\t: (headers as Record<string, unknown>)[name];\n}\n\n/**\n * Builds a {@link RequestRateLimitError} from a provider error response, reading the reset epoch from the\n * standard `x-ratelimit-reset` header when present. Accepts both header shapes in use: the `fetch` `Headers`\n * instance the direct clients get, and the plain object the SDK attaches to its errors.\n */\nexport function toRateLimitError(\n\tex: Error & { response?: { headers?: ResponseHeaders } },\n\ttoken: string | undefined,\n): RequestRateLimitError {\n\tconst raw = getResponseHeader(ex.response?.headers, 'x-ratelimit-reset');\n\n\t// Only a header that actually came back as a string/number can be a reset epoch; anything else (a nested SDK\n\t// object, an array of values) would stringify to garbage and parse to NaN anyway.\n\tlet resetAt: number | undefined;\n\tif (typeof raw === 'string' || typeof raw === 'number') {\n\t\tresetAt = parseInt(String(raw), 10);\n\t\tif (Number.isNaN(resetAt)) {\n\t\t\tresetAt = undefined;\n\t\t}\n\t}\n\n\treturn new RequestRateLimitError(ex, token, resetAt);\n}\n\n/**\n * Normalizes a caught `unknown` into an `Error`. Result cores type their failure channel as `error: Error`,\n * but a `catch` binding is `unknown` and a provider (or a third-party SDK) can throw a non-Error value;\n * returning it raw would leak a non-Error through the public result surface and break downstream `instanceof`\n * classification. Passes an existing `Error` through unchanged and wraps anything else with `String(ex)`.\n */\nexport function toError(ex: unknown): Error {\n\treturn ex instanceof Error ? ex : new Error(String(ex));\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"errors.js","names":[],"sources":["../../../../plus/integrations/src/errors.ts"],"sourcesContent":["export type { AuthTokenInfo } from '@gitlens/git/errors.js';\nexport {\n\tAuthenticationError,\n\tAuthenticationErrorReason,\n\tRequestClientError,\n\tRequestNotFoundError,\n\tRequestRateLimitError,\n} from '@gitlens/git/errors.js';\n\nimport { RequestRateLimitError } from '@gitlens/git/errors.js';\nimport { isCancellationError } from '@gitlens/utils/cancellation.js';\n\nconst unreachableErrorCodes = new Set([\n\t'ECONNREFUSED',\n\t'ECONNRESET',\n\t'ECONNABORTED',\n\t'ENOTFOUND',\n\t'EAI_AGAIN',\n\t'ETIMEDOUT',\n\t'EHOSTUNREACH',\n\t'ENETUNREACH',\n\t'EPIPE',\n\t'ERR_NETWORK',\n\t'UND_ERR_CONNECT_TIMEOUT',\n\t'UND_ERR_HEADERS_TIMEOUT',\n\t'UND_ERR_BODY_TIMEOUT',\n\t'UND_ERR_SOCKET',\n\t'CERT_HAS_EXPIRED',\n\t'DEPTH_ZERO_SELF_SIGNED_CERT',\n\t'SELF_SIGNED_CERT_IN_CHAIN',\n\t'UNABLE_TO_VERIFY_LEAF_SIGNATURE',\n\t'UNABLE_TO_GET_ISSUER_CERT_LOCALLY',\n\t'ERR_TLS_CERT_ALTNAME_INVALID',\n]);\n\n/** Transport wrappers keep the network failure in `cause` or `original`; inspecting only the wrapper loses it. */\nexport function isProviderUnreachableError(ex: unknown): boolean {\n\tconst pending = [ex];\n\tconst seen = new Set<unknown>();\n\twhile (pending.length > 0) {\n\t\tconst candidate = pending.pop();\n\t\tif (candidate == null || typeof candidate !== 'object' || seen.has(candidate)) continue;\n\n\t\tseen.add(candidate);\n\t\tconst error = candidate as {\n\t\t\tname?: string;\n\t\t\tkind?: string;\n\t\t\tmessage?: string;\n\t\t\tcode?: string;\n\t\t\tstatus?: number;\n\t\t\tresponse?: { status?: number };\n\t\t\treason?: string;\n\t\t\toriginal?: unknown;\n\t\t\tcause?: unknown;\n\t\t\terrors?: unknown[];\n\t\t};\n\t\tif (isCancellationError(candidate)) {\n\t\t\tif (error.reason === 'aborted') return false;\n\t\t\tif (error.reason === 'timeout') return true;\n\t\t}\n\n\t\tconst status = error.status ?? error.response?.status;\n\t\tif (typeof status === 'number' && status >= 400) return status >= 500 && status < 600;\n\n\t\tif (\n\t\t\terror.kind === 'network' ||\n\t\t\terror.reason === 'unreachable' ||\n\t\t\terror.name === 'TimeoutError' ||\n\t\t\terror.name === 'AbortError' ||\n\t\t\terror.name === 'NetworkError' ||\n\t\t\t(typeof error.code === 'string' &&\n\t\t\t\t(unreachableErrorCodes.has(error.code) || error.code.startsWith('ERR_SSL_'))) ||\n\t\t\t(typeof error.message === 'string' &&\n\t\t\t\t/^(?:fetch failed|failed to fetch|network request failed|load failed|NetworkError when attempting to fetch resource\\.?)$/i.test(\n\t\t\t\t\terror.message,\n\t\t\t\t))\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\n\t\tpending.push(error.original, error.cause);\n\t\tif (Array.isArray(error.errors)) {\n\t\t\tpending.push(...error.errors);\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Thrown by a provider read when it can't produce a result for a reason that is NOT \"the account is empty\":\n * a prerequisite is missing (e.g. Trello has no app key) or a required scope can't be resolved (e.g. the\n * Linear viewer id, needed to scope \"my issues\"). Returning an empty/undefined result in these cases would be\n * indistinguishable from a genuinely empty account; throwing this lets the result cores recover it into an\n * `{ error }` the facade surfaces as a warning + `fetchFailed`.\n */\nexport class IntegrationReadUnavailableError extends Error {\n\tconstructor(provider: string, reason: string) {\n\t\tsuper(`${provider} read unavailable: ${reason}`);\n\t\tError.captureStackTrace?.(this, new.target);\n\t}\n}\n\n/**\n * Thrown by integration provider HTTP clients when an upstream request fails.\n */\nexport class ProviderFetchError extends Error {\n\tget status(): number {\n\t\treturn this.response.status;\n\t}\n\n\tget statusText(): string {\n\t\treturn this.response.statusText;\n\t}\n\n\t/**\n\t * Builds the error with the upstream body folded into the message, for clients that hold a `Response` whose\n\t * body has not been read (i.e. every non-`ok` path). Use this rather than the constructor whenever the body is\n\t * still available: the status line alone cannot distinguish a throttled request from a permission failure on\n\t * the statuses hosts overload (see {@link isRateLimitResponse}), and only the body says which one it is.\n\t *\n\t * Never throws: the body is best-effort, so an unreadable, empty, or already-consumed one simply yields the\n\t * status-line-only message the constructor would have produced.\n\t */\n\tstatic async fromResponse(provider: string, response: Response): Promise<ProviderFetchError> {\n\t\treturn new ProviderFetchError(provider, response, await readErrorBodyMessage(response));\n\t}\n\n\tconstructor(\n\t\tprovider: string,\n\t\tpublic readonly response: Response,\n\t\terrors?: { message: string }[],\n\t) {\n\t\tsuper(\n\t\t\t`${provider} request failed: ${!response.ok ? `(${response.status}) ${response.statusText}. ` : ''}${\n\t\t\t\terrors?.length ? errors[0].message : ''\n\t\t\t}`,\n\t\t);\n\n\t\tError.captureStackTrace?.(this, new.target);\n\t}\n}\n\n/** Cap on the body text folded into an error message, so an HTML error page can't become the message. */\nconst maxErrorBodyLength = 500;\n\n/**\n * Best-effort human-readable message from an error response body, in the `errors` shape the\n * {@link ProviderFetchError} constructor takes. Tolerant by design — every host in use words its errors\n * differently and some do not send JSON at all:\n * - Azure DevOps — `{ message: \"TF400733: ...\" }`\n * - Bitbucket — `{ error: { message: \"...\" } }`, and bare text for a throttled request\n * - GitLab — `{ message: \"...\" }` or `{ error: \"...\" }`\n * Anything unrecognized falls back to the raw text, which is what the substring check wants anyway.\n */\nasync function readErrorBodyMessage(response: Response): Promise<{ message: string }[] | undefined> {\n\tlet text;\n\ttry {\n\t\t// `bodyUsed` is not a guarantee (a stream can fail mid-read), hence the catch — but it avoids the throw\n\t\t// entirely on the common path where something upstream already consumed the body.\n\t\tif (response.bodyUsed) return undefined;\n\n\t\ttext = (await response.text())?.trim();\n\t} catch {\n\t\treturn undefined;\n\t}\n\tif (!text) return undefined;\n\n\tlet message: string | undefined;\n\ttry {\n\t\tconst body: unknown = JSON.parse(text);\n\t\tif (body != null && typeof body === 'object') {\n\t\t\tconst { message: m, error } = body as { message?: unknown; error?: unknown };\n\t\t\tif (typeof m === 'string') {\n\t\t\t\tmessage = m;\n\t\t\t} else if (typeof error === 'string') {\n\t\t\t\tmessage = error;\n\t\t\t} else if (error != null && typeof error === 'object') {\n\t\t\t\t// Some hosts nest it as `{ error: { message } }`; narrow the same way as the outer object.\n\t\t\t\tconst nested = (error as { message?: unknown }).message;\n\t\t\t\tif (typeof nested === 'string') {\n\t\t\t\t\tmessage = nested;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Not JSON — Bitbucket sends bare text for a throttled request, and any host can send an HTML error page.\n\t}\n\n\tmessage = (message ?? text).trim();\n\treturn message ? [{ message: message.slice(0, maxErrorBodyLength) }] : undefined;\n}\n\n/**\n * Whether a provider's error response denotes a rate limit rather than a permission failure. Kept here, in one\n * place, because the distinction is consequential: a rate limit is retryable, while a permission failure is\n * surfaced as `auth` and drives a reconnect prompt — misclassifying one as the other asks the user to\n * re-authenticate a perfectly healthy connection.\n *\n * Which status a throttled request arrives on varies by host, which is why this takes both:\n * - Azure DevOps and Bitbucket Cloud document 429 (learn.microsoft.com .../integrate/concepts/rate-limits).\n * - GitHub documents \"a `403` or `429` response\" for both its primary and secondary limits\n * (docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api).\n * - GitLab uses 403 for some throttles.\n * So 429 alone is decisive, and on 403 the message decides.\n *\n * NOTE the message must actually carry the host's body for the 403 path to work — see\n * {@link ProviderFetchError.fromResponse}. A `ProviderFetchError` built from the status line alone reads\n * \"(403) Forbidden.\" and can never match, which is what made this check dead code on the direct-fetch clients.\n */\nexport function isRateLimitResponse(ex: { status: number; message?: string }): boolean {\n\t// Matches the phrasing hosts actually use: GitHub/Bitbucket \"API rate limit exceeded\", GitLab \"rate limit\n\t// exceeded\", Azure \"Request was blocked due to exceeding usage of resource 'RateLimit'\" / \"TF400733: The\n\t// request has been canceled: Request was blocked due to exceeding usage\".\n\tif (ex.status === 429) return true;\n\n\tconst message = ex.message?.toLowerCase();\n\treturn message != null && (message.includes('rate limit') || message.includes('ratelimit'));\n}\n\n/**\n * A response's headers as either a `fetch` `Headers` instance or the plain object an SDK error carries. Read via\n * duck-typing on `get` rather than `instanceof Headers`, so this works in both the Node and webworker builds\n * without depending on the global being present.\n */\nexport type ResponseHeaders = Pick<Headers, 'get'> | Record<string, unknown>;\n\n/** Reads one header off either shape of {@link ResponseHeaders}; names are the lower-case ones both shapes use. */\nexport function getResponseHeader(headers: ResponseHeaders | undefined, name: string): unknown {\n\tif (headers == null) return undefined;\n\n\treturn typeof headers.get === 'function'\n\t\t? (headers.get as (name: string) => string | null)(name)\n\t\t: (headers as Record<string, unknown>)[name];\n}\n\n/**\n * The user a Jira or Bitbucket Data Center response names in `X-AUSERNAME`: the user the request authenticated as,\n * `anonymous` when its credential did not authenticate, or none (`undefined`) when the response carries no name.\n */\nexport function getAuthenticatedUser(headers: ResponseHeaders | undefined): string | 'anonymous' | undefined {\n\tconst user = getResponseHeader(headers, 'x-ausername');\n\tif (typeof user !== 'string' || user === '') return undefined;\n\n\treturn user.toLowerCase() === 'anonymous' ? 'anonymous' : user;\n}\n\n/**\n * Builds a {@link RequestRateLimitError} from a provider error response, reading the reset epoch from the\n * standard `x-ratelimit-reset` header when present. Accepts both header shapes in use: the `fetch` `Headers`\n * instance the direct clients get, and the plain object the SDK attaches to its errors.\n */\nexport function toRateLimitError(\n\tex: Error & { response?: { headers?: ResponseHeaders } },\n\ttoken: string | undefined,\n): RequestRateLimitError {\n\tconst raw = getResponseHeader(ex.response?.headers, 'x-ratelimit-reset');\n\n\t// Only a header that actually came back as a string/number can be a reset epoch; anything else (a nested SDK\n\t// object, an array of values) would stringify to garbage and parse to NaN anyway.\n\tlet resetAt: number | undefined;\n\tif (typeof raw === 'string' || typeof raw === 'number') {\n\t\tresetAt = parseInt(String(raw), 10);\n\t\tif (Number.isNaN(resetAt)) {\n\t\t\tresetAt = undefined;\n\t\t}\n\t}\n\n\treturn new RequestRateLimitError(ex, token, resetAt);\n}\n\n/**\n * Normalizes a caught `unknown` into an `Error`. Result cores type their failure channel as `error: Error`,\n * but a `catch` binding is `unknown` and a provider (or a third-party SDK) can throw a non-Error value;\n * returning it raw would leak a non-Error through the public result surface and break downstream `instanceof`\n * classification. Passes an existing `Error` through unchanged and wraps anything else with `String(ex)`.\n */\nexport function toError(ex: unknown): Error {\n\treturn ex instanceof Error ? ex : new Error(String(ex));\n}\n"],"mappings":"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"}
@@ -6,7 +6,7 @@ import { AuthenticationSessionLike, CloudIntegrationAuthType, CloudIntegrationCo
6
6
  import { GitCloudHostIntegrationId, GitSelfManagedHostIntegrationId, IntegrationIds, IssuesCloudHostIntegrationId, IssuesSelfManagedHostIntegrationId, SupportedCloudIntegrationIds, isIntegrationId, isSupportedCloudIntegrationId } from "./constants.js";
7
7
  import { Source, Sources } from "./telemetry.js";
8
8
  import { ConfiguredIntegrationsChangeEvent } from "./authentication/configuredIntegrationService.js";
9
- import { ConnectionStateChangeEvent, ProviderBroadenResult, ProviderOrganization, ProviderPageInfo, ProviderPagedResult, ProviderRepositoryShape, ProviderResult, ProviderSweepResult, ProviderWarning, ProviderWarningCause, ProviderWarningCauseReason, ProviderWarningKind, ProviderWarningOmission, ProviderWarningOmissionKind, ProviderWarningOmissionRecovery, ProviderWarningOmissionScope, ProviderWarningScope, ProviderWarningUnreadableItems, RepositoryIdentity, RepositoryResolution, RepositoryResolutionStatus, ResolveRepositoryResult } from "./results.js";
9
+ import { ConnectionStateChangeEvent, ProviderBroadenResult, ProviderOrganization, ProviderPageInfo, ProviderPagedResult, ProviderRepositoryShape, ProviderResult, ProviderSweepResult, ProviderWarning, ProviderWarningCause, ProviderWarningCauseReason, ProviderWarningKind, ProviderWarningOmission, ProviderWarningOmissionKind, ProviderWarningOmissionRecovery, ProviderWarningOmissionScope, ProviderWarningScope, ProviderWarningSelector, ProviderWarningUnreadableItems, RepositoryIdentity, RepositoryResolution, RepositoryResolutionStatus, ResolveRepositoryResult } from "./results.js";
10
10
  import { IssueFilter } from "./providerFilters.js";
11
11
  import { IssueEtagInclude, PullRequestEtagInclude } from "./models/integration.js";
12
12
  import { IssueCountResult, IssueCountScope, PullRequestCountResult, PullRequestCountScope } from "./reads/counts.js";
@@ -78,5 +78,5 @@ export interface IntegrationManagerContext {
78
78
  */
79
79
  export declare function createIntegrationManager(ctx: IntegrationManagerContext): IntegrationManager;
80
80
  //#endregion
81
- export { type Account, type AccountProvider, type AuthenticationSessionLike, type AuthenticationSessionsChangeEvent, type ClosedPullRequestSweepOptions, type CloudIntegrationAuthType, type CloudIntegrationConnection, type CloudIntegrationType, type ConfigChangeEvent, type ConfigProvider, type ConfiguredIntegrationDescriptor, type ConfiguredIntegrationsChangeEvent, type ConnectionStateChangeEvent, type CurrentAccountResult, type FieldPresence, GitCloudHostIntegrationId, GitSelfManagedHostIntegrationId, type HttpProvider, type IntegrationAuthenticationProvider, type IntegrationAuthenticationProviderDescriptor, type IntegrationAuthenticationSessionDescriptor, type IntegrationIds, type IntegrationManager, type IntegrationServiceHooks, type IntegrationStorageProvider, type IntegrationsRemoteConfig, type IssueBatchResult, type IssueBatchTarget, type IssueCountResult, type IssueCountScope, type IssueEtagInclude, type IssueFieldGroup, IssueFilter, type IssueProjection, type IssueSearchCapabilities, type IssueSearchCriteria, type IssueSearchRelationship, type IssueStateFilter, IssuesCloudHostIntegrationId, IssuesSelfManagedHostIntegrationId, type ListOrgsOptions, type ListProjectsOptions, type ManualTokenAuthProviderOptions, type ProviderAuthenticationSession, type ProviderBroadenOrg, type ProviderBroadenResult, type ProviderOrganization, type ProviderPageInfo, type ProviderPagedResult, type ProviderRepositoriesInput, type ProviderRepositoryInput, type ProviderRepositoryShape, type ProviderResult, type ProviderSweepResult, type ProviderSweepTarget, type ProviderSweepTargetEvent, type ProviderWarning, type ProviderWarningCause, type ProviderWarningCauseReason, type ProviderWarningKind, type ProviderWarningOmission, type ProviderWarningOmissionKind, type ProviderWarningOmissionRecovery, type ProviderWarningOmissionScope, type ProviderWarningScope, type ProviderWarningUnreadableItems, type PullRequestBatchResult, type PullRequestBatchTarget, type PullRequestBranchResult, type PullRequestBranchTarget, type PullRequestCountResult, type PullRequestCountScope, type PullRequestEtagInclude, type PullRequestFieldGroup, PullRequestFilter, type PullRequestProjection, type PullRequestSearchCapabilities, type PullRequestSearchCriteria, type PullRequestStateFilter, type PullRequestSweepOptions, type RepositoriesProvider, type RepositoryIdentity, type RepositoryResolution, type RepositoryResolutionStatus, type ResolveRepositoryResult, type Source, type Sources, type SupportedCloudIntegrationIds, areDomainsOnSameHost, createManualTokenAuthProvider, getIssueFieldPresence, getPullRequestFieldPresence, hostFromDomain, isIntegrationId, isSupportedCloudIntegrationId, toCloudIntegrationType, toIntegrationId };
81
+ export { type Account, type AccountProvider, type AuthenticationSessionLike, type AuthenticationSessionsChangeEvent, type ClosedPullRequestSweepOptions, type CloudIntegrationAuthType, type CloudIntegrationConnection, type CloudIntegrationType, type ConfigChangeEvent, type ConfigProvider, type ConfiguredIntegrationDescriptor, type ConfiguredIntegrationsChangeEvent, type ConnectionStateChangeEvent, type CurrentAccountResult, type FieldPresence, GitCloudHostIntegrationId, GitSelfManagedHostIntegrationId, type HttpProvider, type IntegrationAuthenticationProvider, type IntegrationAuthenticationProviderDescriptor, type IntegrationAuthenticationSessionDescriptor, type IntegrationIds, type IntegrationManager, type IntegrationServiceHooks, type IntegrationStorageProvider, type IntegrationsRemoteConfig, type IssueBatchResult, type IssueBatchTarget, type IssueCountResult, type IssueCountScope, type IssueEtagInclude, type IssueFieldGroup, IssueFilter, type IssueProjection, type IssueSearchCapabilities, type IssueSearchCriteria, type IssueSearchRelationship, type IssueStateFilter, IssuesCloudHostIntegrationId, IssuesSelfManagedHostIntegrationId, type ListOrgsOptions, type ListProjectsOptions, type ManualTokenAuthProviderOptions, type ProviderAuthenticationSession, type ProviderBroadenOrg, type ProviderBroadenResult, type ProviderOrganization, type ProviderPageInfo, type ProviderPagedResult, type ProviderRepositoriesInput, type ProviderRepositoryInput, type ProviderRepositoryShape, type ProviderResult, type ProviderSweepResult, type ProviderSweepTarget, type ProviderSweepTargetEvent, type ProviderWarning, type ProviderWarningCause, type ProviderWarningCauseReason, type ProviderWarningKind, type ProviderWarningOmission, type ProviderWarningOmissionKind, type ProviderWarningOmissionRecovery, type ProviderWarningOmissionScope, type ProviderWarningScope, type ProviderWarningSelector, type ProviderWarningUnreadableItems, type PullRequestBatchResult, type PullRequestBatchTarget, type PullRequestBranchResult, type PullRequestBranchTarget, type PullRequestCountResult, type PullRequestCountScope, type PullRequestEtagInclude, type PullRequestFieldGroup, PullRequestFilter, type PullRequestProjection, type PullRequestSearchCapabilities, type PullRequestSearchCriteria, type PullRequestStateFilter, type PullRequestSweepOptions, type RepositoriesProvider, type RepositoryIdentity, type RepositoryResolution, type RepositoryResolutionStatus, type ResolveRepositoryResult, type Source, type Sources, type SupportedCloudIntegrationIds, areDomainsOnSameHost, createManualTokenAuthProvider, getIssueFieldPresence, getPullRequestFieldPresence, hostFromDomain, isIntegrationId, isSupportedCloudIntegrationId, toCloudIntegrationType, toIntegrationId };
82
82
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../plus/integrations/src/index.ts"],"sourcesContent":["// Public facade for `@gitlens/integrations`.\n//\n// External consumers should import from this entry point only, not from the\n// package's internal subpaths, with one exception: the lightweight, token-scoped\n// read API is a supported public subpath (`./lite.js`). It's kept out of this\n// facade on purpose so importing the session-managed manager doesn't eagerly pull\n// in every provider API client. The internal classes (IntegrationService,\n// IntegrationAuthenticationService, etc.) are not part of the public API and\n// may be refactored without semver bumps.\n\nimport type { Account } from '@gitlens/git/models/author.js';\nimport { CacheController } from '@gitlens/utils/promiseCache.js';\nimport type { IntegrationIds } from './constants.js';\nimport type {\n\tAccountProvider,\n\tConfigProvider,\n\tHttpProvider,\n\tIntegrationCacheProvider,\n\tIntegrationServiceHooks,\n\tIntegrationStorageProvider,\n\tRepositoriesProvider,\n} from './context.js';\nimport { createIntegrationService } from './integrationService.js';\nimport type { IntegrationManager } from './manager.js';\n\n/** A cached provider value, which may still be resolving. */\nexport type IntegrationManagerCacheResult<T> = Promise<T | undefined> | T | undefined;\n\n/** Produces an account value on a cache miss. */\nexport type IntegrationManagerCacheLoader<T> = (cacheable: CacheController) => {\n\tvalue: IntegrationManagerCacheResult<T>;\n\texpiresAt?: number;\n};\n\n/** Stable integration identity supplied to the consumer-owned account cache. */\nexport interface IntegrationAccountCacheDescriptor {\n\treadonly id: IntegrationIds;\n\treadonly domain?: string;\n}\n\n/** Cache controls attached to a provider account lookup. */\nexport interface IntegrationManagerCacheOptions {\n\treadonly connectionId?: string;\n\treadonly etag?: string;\n\treadonly expiryOverride?: boolean | number;\n\treadonly expireOnError?: boolean;\n}\n\n/**\n * Optional consumer-owned cache for values reused by the public manager facade.\n *\n * The manager only needs cross-call caching for provider identity lookups. Other caches used by the GitLens\n * extension host are implementation details and deliberately stay out of this contract.\n */\nexport interface IntegrationManagerCacheProvider {\n\tgetCurrentAccount(\n\t\tintegration: IntegrationAccountCacheDescriptor,\n\t\tcacheable: IntegrationManagerCacheLoader<Account>,\n\t\toptions?: IntegrationManagerCacheOptions,\n\t): IntegrationManagerCacheResult<Account>;\n}\n\nfunction loadUncached<T>(loader: IntegrationManagerCacheLoader<T>): IntegrationManagerCacheResult<T> {\n\treturn loader(new CacheController()).value;\n}\n\nconst uncachedIntegrationCacheProvider: IntegrationCacheProvider = {\n\tgetRepositoryMetadata: (_repo, _integration, loader) => loadUncached(loader),\n\tgetRepositoryDefaultBranch: (_repo, _integration, loader) => loadUncached(loader),\n\tgetPullRequestForSha: (_sha, _repo, _integration, loader) => loadUncached(loader),\n\tgetPullRequestForBranch: (_branch, _repo, _integration, loader) => loadUncached(loader),\n\tgetPullRequest: (_id, _resource, _integration, loader) => loadUncached(loader),\n\tgetIssueOrPullRequest: (_id, _type, _resource, _integration, loader) => loadUncached(loader),\n\tgetIssue: (_id, _resource, _integration, loader) => loadUncached(loader),\n\tgetCurrentAccount: (_integration, loader) => loadUncached(loader),\n\t// Nothing is cached, so there is nothing to evict.\n\tdeletePullRequests: () => {},\n};\n\nfunction toIntegrationCacheProvider(cache: IntegrationManagerCacheProvider | undefined): IntegrationCacheProvider {\n\tif (cache == null) return uncachedIntegrationCacheProvider;\n\n\treturn {\n\t\t...uncachedIntegrationCacheProvider,\n\t\tgetCurrentAccount: (integration, loader, options) =>\n\t\t\tcache.getCurrentAccount({ id: integration.id, domain: integration.domain }, loader, options),\n\t};\n}\n\n/**\n * Consumer-facing runtime for {@link createIntegrationManager}.\n *\n * External consumers may omit `cache`; reads then execute their loaders directly without cross-call caching.\n * The extension host's broader integration context remains private to the implementation.\n */\nexport interface IntegrationManagerContext {\n\treadonly storage: IntegrationStorageProvider;\n\treadonly account: AccountProvider;\n\treadonly config: ConfigProvider;\n\treadonly http: HttpProvider;\n\treadonly cache?: IntegrationManagerCacheProvider;\n\treadonly repositories: RepositoriesProvider;\n\treadonly hooks?: IntegrationServiceHooks;\n}\n\nexport type {\n\tClosedPullRequestSweepOptions,\n\tIntegrationManager,\n\tListOrgsOptions,\n\tListProjectsOptions,\n\t// Every option shape a caller has to BUILD is exported, not just the ones the manager returns:\n\t// `manager.js` is not a public subpath, so a type omitted here can't be named by a consumer at all\n\t// (`broadenIssues`' `orgs` needed `ProviderBroadenOrg` and had to be re-declared downstream).\n\tProviderBroadenOrg,\n\tProviderRepositoriesInput,\n\tProviderRepositoryInput,\n\tProviderSweepTarget,\n\tProviderSweepTargetEvent,\n\tPullRequestSweepOptions,\n} from './manager.js';\n\n/**\n * Construct an `@gitlens/integrations` manager bound to the supplied runtime.\n *\n * The runtime is the **single** cross-boundary contract — anything the\n * package needs (HTTP, storage, cache, auth, subscription, telemetry, UI,\n * configuration, environment) flows through it. The package never imports\n * `vscode`, `Container`, or any consumer-internal types.\n *\n * The returned manager owns its internal services; dispose it (or its\n * containing scope) to release every cached integration plus the runtime's\n * own VS Code subscriptions.\n */\nexport function createIntegrationManager(ctx: IntegrationManagerContext): IntegrationManager {\n\treturn createIntegrationService({\n\t\t...ctx,\n\t\tcache: toIntegrationCacheProvider(ctx.cache),\n\t});\n}\n\n// Re-exports for the public API surface.\nexport type {\n\tAccountProvider,\n\tAuthenticationSessionsChangeEvent,\n\tConfigChangeEvent,\n\tConfigProvider,\n\tRepositoriesProvider,\n\tHttpProvider,\n\tIntegrationsRemoteConfig,\n\tIntegrationServiceHooks,\n\tIntegrationStorageProvider,\n} from './context.js';\nexport type { Source, Sources } from './telemetry.js';\nexport type { IntegrationIds, SupportedCloudIntegrationIds } from './constants.js';\nexport type { ConfiguredIntegrationsChangeEvent } from './authentication/configuredIntegrationService.js';\n\n// Authentication contract — what `IntegrationServiceHooks.createAuthenticationProvider`\n// implementers return. Consumers can plug in any auth strategy (manual token,\n// OAuth, host-managed) by returning an object implementing this interface from\n// the hook.\nexport type {\n\tIntegrationAuthenticationProvider,\n\tIntegrationAuthenticationProviderDescriptor,\n\tIntegrationAuthenticationSessionDescriptor,\n} from './authentication/integrationAuthenticationProvider.js';\nexport type {\n\tAuthenticationSessionLike,\n\tCloudIntegrationAuthType,\n\tCloudIntegrationConnection,\n\tCloudIntegrationType,\n\tConfiguredIntegrationDescriptor,\n\tProviderAuthenticationSession,\n} from './authentication/models.js';\n// Provider-id mapping helpers for consumers bridging their own provider ids to `IntegrationIds`\n// (e.g. mapping multi-account connections from `getConfigured` back to a provider) and vice versa.\nexport { toCloudIntegrationType, toIntegrationId } from './authentication/models.js';\n// Domain normalization is part of connection selection and repository resolution; consumers should use the\n// same implementation rather than importing an internal utility subpath or maintaining a divergent copy.\nexport { areDomainsOnSameHost, hostFromDomain } from './utils/domain.utils.js';\n\n// Convenience: wrap a static access token (env var, CLI flag, secret manager)\n// as an `IntegrationAuthenticationProvider`. For OAuth/refresh flows, implement\n// the interface directly — this helper is for non-interactive consumers only.\nexport {\n\tcreateManualTokenAuthProvider,\n\ttype ManualTokenAuthProviderOptions,\n} from './authentication/manualTokenProvider.js';\n\nexport {\n\tGitCloudHostIntegrationId,\n\tGitSelfManagedHostIntegrationId,\n\tIssuesCloudHostIntegrationId,\n\tIssuesSelfManagedHostIntegrationId,\n\tisIntegrationId,\n\tisSupportedCloudIntegrationId,\n} from './constants.js';\n\n// Neutral pagination + warning result types the Kepler ProviderBackend adapter maps to its own DTOs.\n// These carry no `@gitkraken/provider-apis` types, so consumers depend only on `@gitkraken/core-gitlens`.\nexport type {\n\tConnectionStateChangeEvent,\n\tProviderBroadenResult,\n\tProviderPagedResult,\n\tProviderPageInfo,\n\tProviderResult,\n\tProviderSweepResult,\n\tProviderWarning,\n\tProviderWarningCause,\n\tProviderWarningCauseReason,\n\tProviderWarningKind,\n\tProviderWarningOmission,\n\tProviderWarningOmissionKind,\n\tProviderWarningOmissionRecovery,\n\tProviderWarningOmissionScope,\n\tProviderWarningScope,\n\tProviderWarningUnreadableItems,\n\tProviderOrganization,\n\tProviderRepositoryShape,\n\tRepositoryIdentity,\n\tRepositoryResolution,\n\tRepositoryResolutionStatus,\n\tResolveRepositoryResult,\n} from './results.js';\n// Runtime enums — re-exported as values (not `export type`) so consumers can read their members.\nexport { IssueFilter, PullRequestFilter } from './providerFilters.js';\n// The filtered issue search's criteria model and the capability table that says which of it a provider honors.\n// String unions and plain interfaces, so a consumer builds criteria without importing an internal subpath.\nexport type { IssueSearchCapabilities, IssueSearchCriteria, IssueSearchRelationship } from './providerFilters.js';\n// Account-wide pull-request search criteria and the per-provider capability table.\nexport type { PullRequestSearchCapabilities, PullRequestSearchCriteria } from './providerFilters.js';\n// The count-only issue and pull-request probes' input and result shapes.\nexport type {\n\tIssueCountResult,\n\tIssueCountScope,\n\tPullRequestCountResult,\n\tPullRequestCountScope,\n} from './reads/counts.js';\nexport type { IssueBatchResult, IssueBatchTarget } from './reads/issueBatch.js';\nexport type { PullRequestBatchResult, PullRequestBatchTarget } from './reads/pullRequestBatch.js';\nexport type { IssueEtagInclude, PullRequestEtagInclude } from './models/integration.js';\nexport type { PullRequestBranchResult, PullRequestBranchTarget } from './reads/pullRequestBranches.js';\n// The current-account read's result, and the account shape every identity-bearing read already returns.\nexport type { CurrentAccountResult } from './reads/currentAccount.js';\nexport type { Account } from '@gitlens/git/models/author.js';\n// Cross-provider PR/issue state filters (string unions in the git models).\nexport type { PullRequestStateFilter } from '@gitlens/git/models/pullRequest.js';\nexport type { IssueStateFilter } from '@gitlens/git/models/issue.js';\n// Which read produced a row, and which of its fields that read fetched.\nexport type { PullRequestProjection } from '@gitlens/git/models/pullRequest.js';\nexport type { IssueProjection } from '@gitlens/git/models/issue.js';\nexport type { FieldPresence, IssueFieldGroup, PullRequestFieldGroup } from './fieldPresence.js';\nexport { getIssueFieldPresence, getPullRequestFieldPresence } from './fieldPresence.js';\n"],"mappings":";;;;;;;;;;AA8DA,SAAS,aAAgB,QAA4E;CACpG,OAAO,OAAO,IAAI,gBAAgB,CAAC,CAAC,CAAC;AACtC;AAEA,MAAM,mCAA6D;CAClE,wBAAwB,OAAO,cAAc,WAAW,aAAa,MAAM;CAC3E,6BAA6B,OAAO,cAAc,WAAW,aAAa,MAAM;CAChF,uBAAuB,MAAM,OAAO,cAAc,WAAW,aAAa,MAAM;CAChF,0BAA0B,SAAS,OAAO,cAAc,WAAW,aAAa,MAAM;CACtF,iBAAiB,KAAK,WAAW,cAAc,WAAW,aAAa,MAAM;CAC7E,wBAAwB,KAAK,OAAO,WAAW,cAAc,WAAW,aAAa,MAAM;CAC3F,WAAW,KAAK,WAAW,cAAc,WAAW,aAAa,MAAM;CACvE,oBAAoB,cAAc,WAAW,aAAa,MAAM;CAEhE,0BAA0B,CAAC;AAC5B;AAEA,SAAS,2BAA2B,OAA8E;CACjH,IAAI,SAAS,MAAM,OAAO;CAE1B,OAAO;EACN,GAAG;EACH,oBAAoB,aAAa,QAAQ,YACxC,MAAM,kBAAkB;GAAE,IAAI,YAAY;GAAI,QAAQ,YAAY;EAAO,GAAG,QAAQ,OAAO;CAC7F;AACD;;;;;;;;;;;;;AA8CA,SAAgB,yBAAyB,KAAoD;CAC5F,OAAO,yBAAyB;EAC/B,GAAG;EACH,OAAO,2BAA2B,IAAI,KAAK;CAC5C,CAAC;AACF"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../plus/integrations/src/index.ts"],"sourcesContent":["// Public facade for `@gitlens/integrations`.\n//\n// External consumers should import from this entry point only, not from the\n// package's internal subpaths, with one exception: the lightweight, token-scoped\n// read API is a supported public subpath (`./lite.js`). It's kept out of this\n// facade on purpose so importing the session-managed manager doesn't eagerly pull\n// in every provider API client. The internal classes (IntegrationService,\n// IntegrationAuthenticationService, etc.) are not part of the public API and\n// may be refactored without semver bumps.\n\nimport type { Account } from '@gitlens/git/models/author.js';\nimport { CacheController } from '@gitlens/utils/promiseCache.js';\nimport type { IntegrationIds } from './constants.js';\nimport type {\n\tAccountProvider,\n\tConfigProvider,\n\tHttpProvider,\n\tIntegrationCacheProvider,\n\tIntegrationServiceHooks,\n\tIntegrationStorageProvider,\n\tRepositoriesProvider,\n} from './context.js';\nimport { createIntegrationService } from './integrationService.js';\nimport type { IntegrationManager } from './manager.js';\n\n/** A cached provider value, which may still be resolving. */\nexport type IntegrationManagerCacheResult<T> = Promise<T | undefined> | T | undefined;\n\n/** Produces an account value on a cache miss. */\nexport type IntegrationManagerCacheLoader<T> = (cacheable: CacheController) => {\n\tvalue: IntegrationManagerCacheResult<T>;\n\texpiresAt?: number;\n};\n\n/** Stable integration identity supplied to the consumer-owned account cache. */\nexport interface IntegrationAccountCacheDescriptor {\n\treadonly id: IntegrationIds;\n\treadonly domain?: string;\n}\n\n/** Cache controls attached to a provider account lookup. */\nexport interface IntegrationManagerCacheOptions {\n\treadonly connectionId?: string;\n\treadonly etag?: string;\n\treadonly expiryOverride?: boolean | number;\n\treadonly expireOnError?: boolean;\n}\n\n/**\n * Optional consumer-owned cache for values reused by the public manager facade.\n *\n * The manager only needs cross-call caching for provider identity lookups. Other caches used by the GitLens\n * extension host are implementation details and deliberately stay out of this contract.\n */\nexport interface IntegrationManagerCacheProvider {\n\tgetCurrentAccount(\n\t\tintegration: IntegrationAccountCacheDescriptor,\n\t\tcacheable: IntegrationManagerCacheLoader<Account>,\n\t\toptions?: IntegrationManagerCacheOptions,\n\t): IntegrationManagerCacheResult<Account>;\n}\n\nfunction loadUncached<T>(loader: IntegrationManagerCacheLoader<T>): IntegrationManagerCacheResult<T> {\n\treturn loader(new CacheController()).value;\n}\n\nconst uncachedIntegrationCacheProvider: IntegrationCacheProvider = {\n\tgetRepositoryMetadata: (_repo, _integration, loader) => loadUncached(loader),\n\tgetRepositoryDefaultBranch: (_repo, _integration, loader) => loadUncached(loader),\n\tgetPullRequestForSha: (_sha, _repo, _integration, loader) => loadUncached(loader),\n\tgetPullRequestForBranch: (_branch, _repo, _integration, loader) => loadUncached(loader),\n\tgetPullRequest: (_id, _resource, _integration, loader) => loadUncached(loader),\n\tgetIssueOrPullRequest: (_id, _type, _resource, _integration, loader) => loadUncached(loader),\n\tgetIssue: (_id, _resource, _integration, loader) => loadUncached(loader),\n\tgetCurrentAccount: (_integration, loader) => loadUncached(loader),\n\t// Nothing is cached, so there is nothing to evict.\n\tdeletePullRequests: () => {},\n};\n\nfunction toIntegrationCacheProvider(cache: IntegrationManagerCacheProvider | undefined): IntegrationCacheProvider {\n\tif (cache == null) return uncachedIntegrationCacheProvider;\n\n\treturn {\n\t\t...uncachedIntegrationCacheProvider,\n\t\tgetCurrentAccount: (integration, loader, options) =>\n\t\t\tcache.getCurrentAccount({ id: integration.id, domain: integration.domain }, loader, options),\n\t};\n}\n\n/**\n * Consumer-facing runtime for {@link createIntegrationManager}.\n *\n * External consumers may omit `cache`; reads then execute their loaders directly without cross-call caching.\n * The extension host's broader integration context remains private to the implementation.\n */\nexport interface IntegrationManagerContext {\n\treadonly storage: IntegrationStorageProvider;\n\treadonly account: AccountProvider;\n\treadonly config: ConfigProvider;\n\treadonly http: HttpProvider;\n\treadonly cache?: IntegrationManagerCacheProvider;\n\treadonly repositories: RepositoriesProvider;\n\treadonly hooks?: IntegrationServiceHooks;\n}\n\nexport type {\n\tClosedPullRequestSweepOptions,\n\tIntegrationManager,\n\tListOrgsOptions,\n\tListProjectsOptions,\n\t// Every option shape a caller has to BUILD is exported, not just the ones the manager returns:\n\t// `manager.js` is not a public subpath, so a type omitted here can't be named by a consumer at all\n\t// (`broadenIssues`' `orgs` needed `ProviderBroadenOrg` and had to be re-declared downstream).\n\tProviderBroadenOrg,\n\tProviderRepositoriesInput,\n\tProviderRepositoryInput,\n\tProviderSweepTarget,\n\tProviderSweepTargetEvent,\n\tPullRequestSweepOptions,\n} from './manager.js';\n\n/**\n * Construct an `@gitlens/integrations` manager bound to the supplied runtime.\n *\n * The runtime is the **single** cross-boundary contract — anything the\n * package needs (HTTP, storage, cache, auth, subscription, telemetry, UI,\n * configuration, environment) flows through it. The package never imports\n * `vscode`, `Container`, or any consumer-internal types.\n *\n * The returned manager owns its internal services; dispose it (or its\n * containing scope) to release every cached integration plus the runtime's\n * own VS Code subscriptions.\n */\nexport function createIntegrationManager(ctx: IntegrationManagerContext): IntegrationManager {\n\treturn createIntegrationService({\n\t\t...ctx,\n\t\tcache: toIntegrationCacheProvider(ctx.cache),\n\t});\n}\n\n// Re-exports for the public API surface.\nexport type {\n\tAccountProvider,\n\tAuthenticationSessionsChangeEvent,\n\tConfigChangeEvent,\n\tConfigProvider,\n\tRepositoriesProvider,\n\tHttpProvider,\n\tIntegrationsRemoteConfig,\n\tIntegrationServiceHooks,\n\tIntegrationStorageProvider,\n} from './context.js';\nexport type { Source, Sources } from './telemetry.js';\nexport type { IntegrationIds, SupportedCloudIntegrationIds } from './constants.js';\nexport type { ConfiguredIntegrationsChangeEvent } from './authentication/configuredIntegrationService.js';\n\n// Authentication contract — what `IntegrationServiceHooks.createAuthenticationProvider`\n// implementers return. Consumers can plug in any auth strategy (manual token,\n// OAuth, host-managed) by returning an object implementing this interface from\n// the hook.\nexport type {\n\tIntegrationAuthenticationProvider,\n\tIntegrationAuthenticationProviderDescriptor,\n\tIntegrationAuthenticationSessionDescriptor,\n} from './authentication/integrationAuthenticationProvider.js';\nexport type {\n\tAuthenticationSessionLike,\n\tCloudIntegrationAuthType,\n\tCloudIntegrationConnection,\n\tCloudIntegrationType,\n\tConfiguredIntegrationDescriptor,\n\tProviderAuthenticationSession,\n} from './authentication/models.js';\n// Provider-id mapping helpers for consumers bridging their own provider ids to `IntegrationIds`\n// (e.g. mapping multi-account connections from `getConfigured` back to a provider) and vice versa.\nexport { toCloudIntegrationType, toIntegrationId } from './authentication/models.js';\n// Domain normalization is part of connection selection and repository resolution; consumers should use the\n// same implementation rather than importing an internal utility subpath or maintaining a divergent copy.\nexport { areDomainsOnSameHost, hostFromDomain } from './utils/domain.utils.js';\n\n// Convenience: wrap a static access token (env var, CLI flag, secret manager)\n// as an `IntegrationAuthenticationProvider`. For OAuth/refresh flows, implement\n// the interface directly — this helper is for non-interactive consumers only.\nexport {\n\tcreateManualTokenAuthProvider,\n\ttype ManualTokenAuthProviderOptions,\n} from './authentication/manualTokenProvider.js';\n\nexport {\n\tGitCloudHostIntegrationId,\n\tGitSelfManagedHostIntegrationId,\n\tIssuesCloudHostIntegrationId,\n\tIssuesSelfManagedHostIntegrationId,\n\tisIntegrationId,\n\tisSupportedCloudIntegrationId,\n} from './constants.js';\n\n// Neutral pagination + warning result types the Kepler ProviderBackend adapter maps to its own DTOs.\n// These carry no `@gitkraken/provider-apis` types, so consumers depend only on `@gitkraken/core-gitlens`.\nexport type {\n\tConnectionStateChangeEvent,\n\tProviderBroadenResult,\n\tProviderPagedResult,\n\tProviderPageInfo,\n\tProviderResult,\n\tProviderSweepResult,\n\tProviderWarning,\n\tProviderWarningCause,\n\tProviderWarningCauseReason,\n\tProviderWarningKind,\n\tProviderWarningOmission,\n\tProviderWarningOmissionKind,\n\tProviderWarningOmissionRecovery,\n\tProviderWarningOmissionScope,\n\tProviderWarningScope,\n\tProviderWarningSelector,\n\tProviderWarningUnreadableItems,\n\tProviderOrganization,\n\tProviderRepositoryShape,\n\tRepositoryIdentity,\n\tRepositoryResolution,\n\tRepositoryResolutionStatus,\n\tResolveRepositoryResult,\n} from './results.js';\n// Runtime enums — re-exported as values (not `export type`) so consumers can read their members.\nexport { IssueFilter, PullRequestFilter } from './providerFilters.js';\n// The filtered issue search's criteria model and the capability table that says which of it a provider honors.\n// String unions and plain interfaces, so a consumer builds criteria without importing an internal subpath.\nexport type { IssueSearchCapabilities, IssueSearchCriteria, IssueSearchRelationship } from './providerFilters.js';\n// Account-wide pull-request search criteria and the per-provider capability table.\nexport type { PullRequestSearchCapabilities, PullRequestSearchCriteria } from './providerFilters.js';\n// The count-only issue and pull-request probes' input and result shapes.\nexport type {\n\tIssueCountResult,\n\tIssueCountScope,\n\tPullRequestCountResult,\n\tPullRequestCountScope,\n} from './reads/counts.js';\nexport type { IssueBatchResult, IssueBatchTarget } from './reads/issueBatch.js';\nexport type { PullRequestBatchResult, PullRequestBatchTarget } from './reads/pullRequestBatch.js';\nexport type { IssueEtagInclude, PullRequestEtagInclude } from './models/integration.js';\nexport type { PullRequestBranchResult, PullRequestBranchTarget } from './reads/pullRequestBranches.js';\n// The current-account read's result, and the account shape every identity-bearing read already returns.\nexport type { CurrentAccountResult } from './reads/currentAccount.js';\nexport type { Account } from '@gitlens/git/models/author.js';\n// Cross-provider PR/issue state filters (string unions in the git models).\nexport type { PullRequestStateFilter } from '@gitlens/git/models/pullRequest.js';\nexport type { IssueStateFilter } from '@gitlens/git/models/issue.js';\n// Which read produced a row, and which of its fields that read fetched.\nexport type { PullRequestProjection } from '@gitlens/git/models/pullRequest.js';\nexport type { IssueProjection } from '@gitlens/git/models/issue.js';\nexport type { FieldPresence, IssueFieldGroup, PullRequestFieldGroup } from './fieldPresence.js';\nexport { getIssueFieldPresence, getPullRequestFieldPresence } from './fieldPresence.js';\n"],"mappings":";;;;;;;;;;AA8DA,SAAS,aAAgB,QAA4E;CACpG,OAAO,OAAO,IAAI,gBAAgB,CAAC,CAAC,CAAC;AACtC;AAEA,MAAM,mCAA6D;CAClE,wBAAwB,OAAO,cAAc,WAAW,aAAa,MAAM;CAC3E,6BAA6B,OAAO,cAAc,WAAW,aAAa,MAAM;CAChF,uBAAuB,MAAM,OAAO,cAAc,WAAW,aAAa,MAAM;CAChF,0BAA0B,SAAS,OAAO,cAAc,WAAW,aAAa,MAAM;CACtF,iBAAiB,KAAK,WAAW,cAAc,WAAW,aAAa,MAAM;CAC7E,wBAAwB,KAAK,OAAO,WAAW,cAAc,WAAW,aAAa,MAAM;CAC3F,WAAW,KAAK,WAAW,cAAc,WAAW,aAAa,MAAM;CACvE,oBAAoB,cAAc,WAAW,aAAa,MAAM;CAEhE,0BAA0B,CAAC;AAC5B;AAEA,SAAS,2BAA2B,OAA8E;CACjH,IAAI,SAAS,MAAM,OAAO;CAE1B,OAAO;EACN,GAAG;EACH,oBAAoB,aAAa,QAAQ,YACxC,MAAM,kBAAkB;GAAE,IAAI,YAAY;GAAI,QAAQ,YAAY;EAAO,GAAG,QAAQ,OAAO;CAC7F;AACD;;;;;;;;;;;;;AA8CA,SAAgB,yBAAyB,KAAoD;CAC5F,OAAO,yBAAyB;EAC/B,GAAG;EACH,OAAO,2BAA2B,IAAI,KAAK;CAC5C,CAAC;AACF"}
@@ -67,9 +67,13 @@ export declare abstract class GitHostIntegration<ID extends IntegrationIds = Int
67
67
  }>;
68
68
  /**
69
69
  * {@link resolveRepositoryCoordinates} for the repository descriptors the list and search reads take: those, unless
70
- * the host overrides both.
70
+ * the host overrides both. A scope flagged `unsettled` that then reads nothing is reported as a failure of the read
71
+ * ({@link toUnsettledScopeFailure}) rather than as an empty scope.
71
72
  */
72
- protected resolveRepositoryInputs(_session: ProviderAuthenticationSession, repos: readonly ProviderRepoInput[], _cancellation?: AbortSignal): Promise<ProviderRepoInput[]>;
73
+ protected resolveRepositoryInputs(_session: ProviderAuthenticationSession, repos: readonly ProviderRepoInput[], _cancellation?: AbortSignal): Promise<{
74
+ repos: ProviderRepoInput[];
75
+ unsettled?: readonly boolean[];
76
+ }>;
73
77
  /**
74
78
  * The repositories a repo-scoped read of `repos` addresses ({@link resolveRepositoryInputs}), for a caller that
75
79
  * shapes the read by them before making it. Resolves the session as that read does, and fails as it would: a
@@ -11,7 +11,7 @@ import "../../../git/models/pullRequest.js";
11
11
  import { toError } from "../errors.js";
12
12
  import "../constants.js";
13
13
  import { isAzureProviderId } from "../providers/providerErrors.js";
14
- import { throwIfCallerContractError, toCollectionFailureError, toCollectionScopeFailure } from "../collectionMetadata.js";
14
+ import { throwIfCallerContractError, toCollectionFailureError, toCollectionScopeFailure, toUnsettledScopeFailure, unsettledMissMessage } from "../collectionMetadata.js";
15
15
  import { toTokenWithInfo } from "../authentication/models.js";
16
16
  import "../providerFilters.js";
17
17
  import { areDomainsOnSameHost } from "../utils/domain.utils.js";
@@ -39,10 +39,17 @@ function rejectUnsettledMisses(slots, unsettled, isMiss) {
39
39
  if (!unsettled?.some(Boolean)) return slots;
40
40
  return slots.map((slot, i) => unsettled[i] && slot.status === "fulfilled" && isMiss(slot.value) ? {
41
41
  status: "rejected",
42
- reason: /* @__PURE__ */ new Error("Nothing read for a repository that couldn't be settled")
42
+ reason: new Error(unsettledMissMessage)
43
43
  } : slot);
44
44
  }
45
45
  /**
46
+ * The keys of the scopes {@link GitHostIntegration.resolveRepositoryInputs} couldn't settle, for a list read to record
47
+ * a miss for one as a failure ({@link toUnsettledScopeFailure}) rather than as an empty scope.
48
+ */
49
+ function toUnsettledScopeKeys(repos, unsettled, key) {
50
+ return new Set(unsettled?.some(Boolean) ? repos.filter((_, i) => unsettled[i]).map(key) : []);
51
+ }
52
+ /**
46
53
  * Rejects a read the provider can't serve as asked: logs the reason and returns it as the `{ error }` half of an
47
54
  * {@link IntegrationResult}, timed from `start`.
48
55
  *
@@ -94,10 +101,11 @@ var GitHostIntegration = class extends IntegrationBase {
94
101
  }
95
102
  /**
96
103
  * {@link resolveRepositoryCoordinates} for the repository descriptors the list and search reads take: those, unless
97
- * the host overrides both.
104
+ * the host overrides both. A scope flagged `unsettled` that then reads nothing is reported as a failure of the read
105
+ * ({@link toUnsettledScopeFailure}) rather than as an empty scope.
98
106
  */
99
107
  resolveRepositoryInputs(_session, repos, _cancellation) {
100
- return Promise.resolve([...repos]);
108
+ return Promise.resolve({ repos: [...repos] });
101
109
  }
102
110
  /**
103
111
  * The repositories a repo-scoped read of `repos` addresses ({@link resolveRepositoryInputs}), for a caller that
@@ -111,7 +119,7 @@ var GitHostIntegration = class extends IntegrationBase {
111
119
  const session = await this.resolveReadSession(connectionId, void 0);
112
120
  if (session == null || isReadSessionFailure(session)) return session && { error: session.error };
113
121
  try {
114
- return { value: await this.resolveRepositoryInputs(session, repos) };
122
+ return { value: (await this.resolveRepositoryInputs(session, repos)).repos };
115
123
  } catch {
116
124
  return { value: repos };
117
125
  }
@@ -538,10 +546,12 @@ var GitHostIntegration = class extends IntegrationBase {
538
546
  if (session == null || isReadSessionFailure(session)) return session && { error: session.error };
539
547
  const start = performance.now();
540
548
  let resolvedRepos;
549
+ let unsettled;
541
550
  let customUrl;
542
551
  let api;
543
552
  try {
544
- resolvedRepos = isRepoIdsInput(repos) ? repos : await this.resolveRepositoryInputs(session, repos);
553
+ if (isRepoIdsInput(repos)) resolvedRepos = repos;
554
+ else ({repos: resolvedRepos, unsettled} = await this.resolveRepositoryInputs(session, repos));
545
555
  customUrl = options?.customUrl ?? (isGitSelfManagedHostIntegrationId(providerId) ? this.getRepositoriesApiBaseUrl(session, resolvedRepos) : void 0);
546
556
  api = await this.getProvidersApi();
547
557
  } catch (ex) {
@@ -592,6 +602,7 @@ var GitHostIntegration = class extends IntegrationBase {
592
602
  mentionLogin: options.filters.includes("mention") ? userFilterProperty : void 0
593
603
  };
594
604
  }
605
+ const unsettledProjects = toUnsettledScopeKeys(reposOrRepoIds, unsettled, (r) => `${r.namespace}\0${r.project}`);
595
606
  const cursors = this.parseCursorInfo(options?.cursor).cursors ?? [];
596
607
  let projectInputs = Array.from(projects.values(), (project) => ({
597
608
  namespace: organization,
@@ -642,6 +653,17 @@ var GitHostIntegration = class extends IntegrationBase {
642
653
  data.push(...results.values);
643
654
  if (results.paging?.truncated) truncated = true;
644
655
  metadata = mergeCollectionMetadata(metadata, results.metadata);
656
+ if (projectInput.cursor == null && results.values.length === 0 && unsettledProjects.has(`${projectInput.namespace}\0${projectInput.project}`)) {
657
+ truncated = true;
658
+ metadata = mergeCollectionMetadata(metadata, {
659
+ completeness: "partial",
660
+ failures: [toUnsettledScopeFailure({
661
+ providerId,
662
+ resourceId: projectInput.namespace,
663
+ projectId: projectInput.project
664
+ })]
665
+ });
666
+ }
645
667
  if (results.paging?.more) {
646
668
  hasMore = true;
647
669
  cursor.cursors.push({
@@ -871,10 +893,12 @@ var GitHostIntegration = class extends IntegrationBase {
871
893
  if (session == null || isReadSessionFailure(session)) return session && { error: session.error };
872
894
  const start = performance.now();
873
895
  let resolvedRepos;
896
+ let unsettled;
874
897
  let customUrl;
875
898
  let api;
876
899
  try {
877
- resolvedRepos = isRepoIdsInput(repos) ? repos : await this.resolveRepositoryInputs(session, repos);
900
+ if (isRepoIdsInput(repos)) resolvedRepos = repos;
901
+ else ({repos: resolvedRepos, unsettled} = await this.resolveRepositoryInputs(session, repos));
878
902
  customUrl = options?.customUrl ?? (isGitSelfManagedHostIntegrationId(providerId) ? this.getRepositoriesApiBaseUrl(session, resolvedRepos) : void 0);
879
903
  api = await this.getProvidersApi();
880
904
  } catch (ex) {
@@ -963,6 +987,8 @@ var GitHostIntegration = class extends IntegrationBase {
963
987
  };
964
988
  }
965
989
  if (api.getProviderPullRequestsPagingMode(providerId) === "repo" && !api.isRepoIdsInput(reposOrRepoIds)) {
990
+ const toRepoInputKey = (r) => `${r.namespace}\0${r.project ?? ""}\0${r.name}`;
991
+ const unsettledRepos = toUnsettledScopeKeys(reposOrRepoIds, unsettled, toRepoInputKey);
966
992
  const cursors = this.parseCursorInfo(options?.cursor).cursors ?? [];
967
993
  let repoInputs = reposOrRepoIds.map((repo) => ({
968
994
  repo,
@@ -1004,6 +1030,10 @@ var GitHostIntegration = class extends IntegrationBase {
1004
1030
  const { repoInput, results } = outcome.value;
1005
1031
  data.push(...results.values);
1006
1032
  metadata = mergeCollectionMetadata(metadata, results.metadata);
1033
+ if (repoInput.cursor == null && results.values.length === 0 && unsettledRepos.has(toRepoInputKey(repoInput.repo))) failures.push(toUnsettledScopeFailure({
1034
+ providerId,
1035
+ repositoryId: `${repoInput.repo.namespace}/${repoInput.repo.name}`
1036
+ }));
1007
1037
  if (results.paging?.truncated) truncated = true;
1008
1038
  if (results.paging?.more) {
1009
1039
  hasMore = true;