@gitkraken/core-gitlens 0.20.2 → 0.22.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 (67) hide show
  1. package/CHANGELOG.md +21 -1
  2. package/dist/git/models/issue.d.ts +30 -1
  3. package/dist/git/models/issue.js +3 -1
  4. package/dist/git/models/issue.js.map +1 -1
  5. package/dist/git/utils/autolink.utils.d.ts +4 -1
  6. package/dist/git/utils/autolink.utils.js +12 -3
  7. package/dist/git/utils/autolink.utils.js.map +1 -1
  8. package/dist/git/utils/issue.utils.js +2 -1
  9. package/dist/git/utils/issue.utils.js.map +1 -1
  10. package/dist/plus/integrations/authentication/configuredIntegrationService.d.ts +7 -0
  11. package/dist/plus/integrations/authentication/configuredIntegrationService.js +12 -0
  12. package/dist/plus/integrations/authentication/configuredIntegrationService.js.map +1 -1
  13. package/dist/plus/integrations/authentication/integrationAuthenticationService.js +5 -3
  14. package/dist/plus/integrations/authentication/integrationAuthenticationService.js.map +1 -1
  15. package/dist/plus/integrations/authentication/models.d.ts +9 -0
  16. package/dist/plus/integrations/authentication/models.js +13 -1
  17. package/dist/plus/integrations/authentication/models.js.map +1 -1
  18. package/dist/plus/integrations/authentication/observedAuthenticationProvider.d.ts +34 -0
  19. package/dist/plus/integrations/authentication/observedAuthenticationProvider.js +227 -0
  20. package/dist/plus/integrations/authentication/observedAuthenticationProvider.js.map +1 -0
  21. package/dist/plus/integrations/index.d.ts +4 -2
  22. package/dist/plus/integrations/index.js.map +1 -1
  23. package/dist/plus/integrations/integrationService.d.ts +9 -4
  24. package/dist/plus/integrations/integrationService.js +30 -7
  25. package/dist/plus/integrations/integrationService.js.map +1 -1
  26. package/dist/plus/integrations/manager.d.ts +18 -1
  27. package/dist/plus/integrations/models/integration.d.ts +21 -2
  28. package/dist/plus/integrations/models/integration.js +87 -11
  29. package/dist/plus/integrations/models/integration.js.map +1 -1
  30. package/dist/plus/integrations/models/issuesIntegration.d.ts +20 -1
  31. package/dist/plus/integrations/models/issuesIntegration.js +106 -2
  32. package/dist/plus/integrations/models/issuesIntegration.js.map +1 -1
  33. package/dist/plus/integrations/providers/jira-server.d.ts +10 -2
  34. package/dist/plus/integrations/providers/jira-server.js +74 -7
  35. package/dist/plus/integrations/providers/jira-server.js.map +1 -1
  36. package/dist/plus/integrations/providers/jira.d.ts +1 -1
  37. package/dist/plus/integrations/providers/jira.js +3 -25
  38. package/dist/plus/integrations/providers/jira.js.map +1 -1
  39. package/dist/plus/integrations/providers/linear.d.ts +1 -1
  40. package/dist/plus/integrations/providers/linear.js +3 -27
  41. package/dist/plus/integrations/providers/linear.js.map +1 -1
  42. package/dist/plus/integrations/providers/linearIssuesEtag.d.ts +20 -4
  43. package/dist/plus/integrations/providers/linearIssuesEtag.js +42 -6
  44. package/dist/plus/integrations/providers/linearIssuesEtag.js.map +1 -1
  45. package/dist/plus/integrations/providers/models.js +15 -2
  46. package/dist/plus/integrations/providers/models.js.map +1 -1
  47. package/dist/plus/integrations/providers/providerErrors.d.ts +2 -0
  48. package/dist/plus/integrations/providers/providerErrors.js +5 -2
  49. package/dist/plus/integrations/providers/providerErrors.js.map +1 -1
  50. package/dist/plus/integrations/providers/trello.d.ts +1 -1
  51. package/dist/plus/integrations/providers/trello.js +1 -1
  52. package/dist/plus/integrations/providers/trello.js.map +1 -1
  53. package/dist/plus/integrations/providers/utils/issueAutolinks.d.ts +8 -0
  54. package/dist/plus/integrations/providers/utils/issueAutolinks.js +20 -0
  55. package/dist/plus/integrations/providers/utils/issueAutolinks.js.map +1 -0
  56. package/dist/plus/integrations/reads/autolinks.d.ts +7 -0
  57. package/dist/plus/integrations/reads/autolinks.js +40 -0
  58. package/dist/plus/integrations/reads/autolinks.js.map +1 -0
  59. package/dist/plus/integrations/reads/context.d.ts +4 -2
  60. package/dist/plus/integrations/reads/etag.js +3 -1
  61. package/dist/plus/integrations/reads/etag.js.map +1 -1
  62. package/dist/plus/integrations/reads/hierarchy.js +1 -1
  63. package/dist/plus/integrations/reads/issueBatch.js +1 -1
  64. package/dist/plus/integrations/reads/issueTracker.js +1 -1
  65. package/dist/plus/integrations/reads/resolveRepository.js +1 -1
  66. package/docs/integrations.md +34 -2
  67. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"configuredIntegrationService.js","names":[],"sources":["../../../../../plus/integrations/src/authentication/configuredIntegrationService.ts"],"sourcesContent":["import { debounce } from '@gitlens/utils/debounce.js';\nimport type { Disposable } from '@gitlens/utils/disposable.js';\nimport type { Event } from '@gitlens/utils/event.js';\nimport { Emitter } from '@gitlens/utils/event.js';\nimport { flatten } from '@gitlens/utils/iterable.js';\nimport type {\n\tIntegrationIds,\n\tStoredConfiguredIntegrationDescriptor,\n\tStoredIntegrationConfigurations,\n} from '../constants.js';\nimport type { IntegrationServiceContext } from '../context.js';\nimport { providersMetadata } from '../providers/models.js';\nimport {\n\tareDomainsOnSameHost,\n\tbaseUrlFromDomain,\n\thostFromDomain,\n\tsameConfiguredBaseUrl,\n} from '../utils/domain.utils.js';\nimport { isSelfManagedHostIntegrationId } from '../utils/integration.utils.js';\nimport type { IntegrationAuthenticationSessionDescriptor } from './integrationAuthenticationProvider.js';\nimport type {\n\tCloudIntegrationAuthType,\n\tConfiguredIntegrationDescriptor,\n\tConnectionResource,\n\tProviderAuthenticationSession,\n} from './models.js';\n\ninterface StoredSession {\n\tid: string;\n\taccessToken: string;\n\taccount?: { label?: string; displayName?: string; id: string };\n\tscopes: string[];\n\tcloud?: boolean;\n\ttype: CloudIntegrationAuthType | undefined;\n\texpiresAt?: string;\n\tdomain?: string;\n\t/** See {@link ProviderAuthenticationSession.baseUrl}: the configured address, path included. */\n\tbaseUrl?: string;\n\tprotocol?: string;\n\t/** The provider app key paired with the token for providers whose client needs one (e.g. Trello). */\n\tappKey?: string;\n}\n\nexport interface ConfiguredIntegrationsChangeEvent {\n\treadonly added: readonly IntegrationIds[];\n\treadonly removed: readonly IntegrationIds[];\n}\n\nexport class ConfiguredIntegrationService implements Disposable {\n\tprivate readonly _onDidChange = new Emitter<ConfiguredIntegrationsChangeEvent>();\n\tprivate storeConfiguredQueue: Promise<void> = Promise.resolve();\n\t/**\n\t * One provider's secret and descriptor mutations run one at a time, so a sign-out never interleaves with a\n\t * token being stored: storing writes the secret and then registers its descriptor, and a delete in between would\n\t * miss a connection it cannot see yet, or be undone by the pending write (#5948).\n\t */\n\tprivate readonly _locks = new Map<IntegrationIds, Promise<void>>();\n\t/** Monotonic across providers; see {@link getSignOutMark}. */\n\tprivate _signOutEpoch = 0;\n\t/** The epoch of the latest sign-out per scope: a provider, a self-managed host, or a single connection. */\n\tprivate readonly _signOuts = new Map<string, number>();\n\tget onDidChange(): Event<ConfiguredIntegrationsChangeEvent> {\n\t\treturn this._onDidChange.event;\n\t}\n\n\tconstructor(private readonly ctx: IntegrationServiceContext) {}\n\n\tdispose(): void {\n\t\tthis._onDidChange.dispose();\n\t}\n\n\tprivate _configured?: Map<IntegrationIds, ConfiguredIntegrationDescriptor[]>;\n\tprivate get configured(): Map<IntegrationIds, ConfiguredIntegrationDescriptor[]> {\n\t\tif (this._configured == null) {\n\t\t\tthis._configured = new Map<IntegrationIds, ConfiguredIntegrationDescriptor[]>();\n\n\t\t\tconst storedConfigured = this.ctx.storage.get('integrations:configured');\n\t\t\tfor (const [id, configured] of Object.entries(storedConfigured ?? {}) as [\n\t\t\t\tIntegrationIds,\n\t\t\t\tStoredConfiguredIntegrationDescriptor[],\n\t\t\t][]) {\n\t\t\t\tif (configured == null) continue;\n\n\t\t\t\tconst descriptors = configured.map(d => ({\n\t\t\t\t\t...d,\n\t\t\t\t\tbaseUrl: isSelfManagedHostIntegrationId(id) ? getStoredBaseUrl(d.baseUrl, d.domain) : d.baseUrl,\n\t\t\t\t\tdomain: this.normalizeConfiguredDomain(id, d.domain),\n\t\t\t\t\t// Backfill a stable connection id for pre-multi-account stored data: the domain for\n\t\t\t\t\t// self-managed hosts, or the provider's canonical domain for cloud (which is the legacy\n\t\t\t\t\t// secret-key session id), so existing secrets keep resolving with zero migration. Fall back\n\t\t\t\t\t// to the integration id (never empty) when no domain is known — self-managed providers carry\n\t\t\t\t\t// `domain: ''` in metadata, and an empty id would collide across connections and produce\n\t\t\t\t\t// ambiguous secret keys (`...|`).\n\t\t\t\t\tid: d.id || d.domain || providersMetadata[id]?.domain || id,\n\t\t\t\t\texpiresAt: d.expiresAt ? new Date(d.expiresAt) : undefined,\n\t\t\t\t}));\n\t\t\t\tthis._configured.set(id, descriptors);\n\t\t\t}\n\t\t}\n\n\t\treturn this._configured;\n\t}\n\n\t// Synchronous: reads the in-memory configured map (lazily hydrated from storage). No async work —\n\t// the old async variant only existed to weave in the built-in VS Code GitHub session, which is gone.\n\tgetConfigured(\n\t\tid?: IntegrationIds,\n\t\toptions?: { cloud?: boolean; domain?: string },\n\t): ConfiguredIntegrationDescriptor[] {\n\t\tconst descriptors: ConfiguredIntegrationDescriptor[] = [];\n\n\t\tconst configured =\n\t\t\tid != null\n\t\t\t\t? this.configured.get(id)\n\t\t\t\t: [...flatten<ConfiguredIntegrationDescriptor>(this.configured.values())];\n\t\tif (!configured?.length) return descriptors;\n\n\t\tif (options?.domain != null || options?.cloud != null) {\n\t\t\tfor (const descriptor of configured) {\n\t\t\t\tif (\n\t\t\t\t\t(options?.domain != null &&\n\t\t\t\t\t\t!this.domainsMatch(id ?? descriptor.integrationId, descriptor.domain, options.domain)) ||\n\t\t\t\t\t(options?.cloud === true && !descriptor.cloud) ||\n\t\t\t\t\t(options?.cloud === false && descriptor.cloud)\n\t\t\t\t) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tdescriptors.push(descriptor);\n\t\t\t}\n\t\t} else {\n\t\t\tdescriptors.push(...configured);\n\t\t}\n\n\t\treturn descriptors;\n\t}\n\n\tprivate async storeConfigured(): Promise<void> {\n\t\t// We need to convert the map to a record to store\n\t\tconst configured: StoredIntegrationConfigurations = {} as unknown as StoredIntegrationConfigurations;\n\t\tfor (const [id, descriptors] of this.configured) {\n\t\t\tconfigured[id] = descriptors.map(d => ({\n\t\t\t\t...d,\n\t\t\t\texpiresAt: d.expiresAt\n\t\t\t\t\t? d.expiresAt instanceof Date\n\t\t\t\t\t\t? d.expiresAt.toISOString()\n\t\t\t\t\t\t: d.expiresAt\n\t\t\t\t\t: undefined,\n\t\t\t}));\n\t\t}\n\n\t\tconst pending = this.storeConfiguredQueue.then(() =>\n\t\t\tthis.ctx.storage.store('integrations:configured', configured),\n\t\t);\n\t\tthis.storeConfiguredQueue = pending.catch(() => {});\n\t\tawait pending;\n\t}\n\n\tprivate async addOrUpdateConfigured(descriptor: ConfiguredIntegrationDescriptor): Promise<void> {\n\t\tdescriptor = {\n\t\t\t...descriptor,\n\t\t\tbaseUrl: isSelfManagedHostIntegrationId(descriptor.integrationId)\n\t\t\t\t? getStoredBaseUrl(descriptor.baseUrl, descriptor.domain)\n\t\t\t\t: descriptor.baseUrl,\n\t\t\tdomain: this.normalizeConfiguredDomain(descriptor.integrationId, descriptor.domain),\n\t\t};\n\t\tconst descriptors = this.configured.get(descriptor.integrationId) ?? [];\n\t\t// Key connections by their stable id (+ cloud, to preserve legacy local/cloud coexistence) so\n\t\t// multiple accounts on the same provider+domain no longer overwrite each other.\n\t\tconst existing = descriptors.find(d => d.id === descriptor.id && d.cloud === descriptor.cloud);\n\n\t\t// The first connection for a provider/domain is primary by default; an explicit flag (or the\n\t\t// existing value) always wins. Self-managed providers can span multiple hosts under the same\n\t\t// integration id, so each host needs its own primary.\n\t\tconst primaryScope = this.getPrimaryScope(descriptor.integrationId, descriptors, descriptor.domain);\n\t\tconst primary = descriptor.primary ?? existing?.primary ?? !primaryScope.some(d => d.primary);\n\t\t// Preserve a previously-resolved type/accountName when the incoming write doesn't carry them (e.g.\n\t\t// the model re-stores the primary session with an empty account, after reconcile enriched it).\n\t\tconst type = descriptor.type ?? existing?.type;\n\t\tconst accountName = descriptor.accountName ?? existing?.accountName;\n\t\t// A write without a workspace (a failed lookup, or a session re-store) keeps the stored pair whole.\n\t\tconst resource = descriptor.resourceId != null ? descriptor : existing;\n\t\tconst normalized: ConfiguredIntegrationDescriptor = {\n\t\t\t...descriptor,\n\t\t\tprimary: primary,\n\t\t\ttype: type,\n\t\t\taccountName: accountName,\n\t\t\tresourceName: resource?.resourceName,\n\t\t\tresourceId: resource?.resourceId,\n\t\t};\n\n\t\tlet changed: boolean;\n\t\tif (existing != null) {\n\t\t\t// `baseUrl` is compared alongside `domain`, not folded into it: `domain` is normalized to a bare\n\t\t\t// host, so a connection re-pointed to another context path on the SAME host is identical by domain\n\t\t\t// and would otherwise be treated as unchanged — leaving the stored descriptor, and every warm\n\t\t\t// integration listening for the change, on the old address.\n\t\t\tif (\n\t\t\t\texisting.domain === normalized.domain &&\n\t\t\t\tsameConfiguredBaseUrl(existing.baseUrl, normalized.baseUrl) &&\n\t\t\t\texisting.expiresAt === normalized.expiresAt &&\n\t\t\t\texisting.scopes === normalized.scopes &&\n\t\t\t\t(existing.primary ?? false) === (normalized.primary ?? false) &&\n\t\t\t\texisting.type === normalized.type &&\n\t\t\t\texisting.accountName === normalized.accountName &&\n\t\t\t\texisting.resourceName === normalized.resourceName &&\n\t\t\t\texisting.resourceId === normalized.resourceId\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Only fire the change event on address/scopes/primary/type/accountName changes (ignore expiresAt churn)\n\t\t\tchanged =\n\t\t\t\texisting.domain !== normalized.domain ||\n\t\t\t\t!sameConfiguredBaseUrl(existing.baseUrl, normalized.baseUrl) ||\n\t\t\t\texisting.scopes !== normalized.scopes ||\n\t\t\t\t(existing.primary ?? false) !== (normalized.primary ?? false) ||\n\t\t\t\texisting.type !== normalized.type ||\n\t\t\t\texisting.accountName !== normalized.accountName ||\n\t\t\t\texisting.resourceName !== normalized.resourceName ||\n\t\t\t\texisting.resourceId !== normalized.resourceId;\n\n\t\t\t// remove the existing descriptor from the array\n\t\t\tdescriptors.splice(descriptors.indexOf(existing), 1);\n\t\t} else {\n\t\t\tchanged = true;\n\t\t}\n\n\t\tdescriptors.push(normalized);\n\t\tthis.configured.set(descriptor.integrationId, descriptors);\n\n\t\tif (changed) {\n\t\t\tthis.fireChange(descriptor.integrationId);\n\t\t}\n\t\tawait this.storeConfigured();\n\t}\n\n\tprivate async removeConfigured(\n\t\tid: IntegrationIds,\n\t\toptions: { connectionId: string; cloud: boolean | undefined },\n\t): Promise<void> {\n\t\tconst existing = this.configured.get(id);\n\t\tif (existing == null || existing.length === 0) return;\n\n\t\tconst removedPrimaryDomains = new Set<string | undefined>();\n\t\tconst descriptors: ConfiguredIntegrationDescriptor[] = [];\n\t\tfor (const d of existing) {\n\t\t\tif (\n\t\t\t\td.id === options.connectionId &&\n\t\t\t\t(options?.cloud == null ||\n\t\t\t\t\t(options?.cloud === true && d.cloud === true) ||\n\t\t\t\t\t(options?.cloud === false && d.cloud === false))\n\t\t\t) {\n\t\t\t\tif (d.primary) {\n\t\t\t\t\tremovedPrimaryDomains.add(d.domain);\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tdescriptors.push(d);\n\t\t}\n\n\t\tif (descriptors.length === existing.length) return; // nothing matched\n\n\t\t// Promote a secondary to primary when the removed connection was the primary and others remain\n\t\t// in the same primary scope, so the provider/host stays in a well-defined connected state.\n\t\tfor (const domain of removedPrimaryDomains) {\n\t\t\tif (descriptors.some(d => this.isInPrimaryScope(id, d, domain) && d.primary)) continue;\n\n\t\t\tconst index = descriptors.findIndex(d => this.isInPrimaryScope(id, d, domain));\n\t\t\tif (index !== -1) {\n\t\t\t\tdescriptors[index] = { ...descriptors[index], primary: true };\n\t\t\t}\n\t\t}\n\n\t\tthis.configured.set(id, descriptors);\n\t\tthis.fireChange(undefined, id);\n\t\tawait this.storeConfigured();\n\t}\n\n\tprivate withLock<T>(id: IntegrationIds, fn: () => Promise<T>): Promise<T> {\n\t\tconst run = (this._locks.get(id) ?? Promise.resolve()).then(fn);\n\t\tconst settled = run.then(\n\t\t\t() => undefined,\n\t\t\t() => undefined,\n\t\t);\n\t\tthis._locks.set(id, settled);\n\t\tvoid settled.then(() => {\n\t\t\tif (this._locks.get(id) === settled) {\n\t\t\t\tthis._locks.delete(id);\n\t\t\t}\n\t\t});\n\t\treturn run;\n\t}\n\n\t/**\n\t * Taken before a token is read or fetched, and handed to {@link storeSession}: a sign-out that lands after it\n\t * (a disconnect, a reauthentication, the connection being removed) refuses the store, so a token fetched across\n\t * it is not written back and reconnected on the next resolution (gitkraken/kepler#3546).\n\t */\n\tgetSignOutMark(): number {\n\t\treturn this._signOutEpoch;\n\t}\n\n\tprivate markSignOut(scope: string): void {\n\t\tthis._signOuts.set(scope, ++this._signOutEpoch);\n\t}\n\n\tprivate getHostScope(id: IntegrationIds, domain: string): string {\n\t\treturn `${id}|host:${hostFromDomain(domain) ?? domain}`;\n\t}\n\n\tprivate isSignedOutSince(id: IntegrationIds, session: ProviderAuthenticationSession, mark: number): boolean {\n\t\tconst since = (scope: string) => (this._signOuts.get(scope) ?? 0) > mark;\n\t\tif (since(id)) return true;\n\t\tif (isSelfManagedHostIntegrationId(id) && session.domain && since(this.getHostScope(id, session.domain))) {\n\t\t\treturn true;\n\t\t}\n\t\treturn since(`${id}|connection:${session.id}`);\n\t}\n\n\t/**\n\t * Stores the session's secret and descriptor together. With a `signOutMark`, nothing is stored, and `false` is\n\t * returned, when a sign-out covering the session landed after the mark was taken.\n\t */\n\tstoreSession(\n\t\tid: IntegrationIds,\n\t\tsession: ProviderAuthenticationSession,\n\t\toptions?: { signOutMark?: number; resource?: ConnectionResource },\n\t): Promise<boolean> {\n\t\treturn this.withLock(id, async () => {\n\t\t\tif (options?.signOutMark != null && this.isSignedOutSince(id, session, options.signOutMark)) return false;\n\n\t\t\tawait this.writeSecret(id, session, options?.resource);\n\t\t\treturn true;\n\t\t});\n\t}\n\n\tgetStoredSession(\n\t\tid: IntegrationIds,\n\t\tdescriptor: IntegrationAuthenticationSessionDescriptor,\n\t): Promise<ProviderAuthenticationSession | undefined> {\n\t\t// Under the lock too: reading can repair storage (a legacy local-key cloud session, a missing descriptor).\n\t\treturn this.withLock(id, async () => {\n\t\t\tconst sessionId = this.resolveConnectionId(id, descriptor);\n\t\t\tlet session = descriptor.cloud === true ? undefined : await this.readSecret(id, sessionId, false);\n\n\t\t\tlet cloudIfMissing = false;\n\t\t\tif (session != null) {\n\t\t\t\t// Check the `expiresAt` field\n\t\t\t\t// If it has an expiresAt property and the key is the old type, then it's a cloud session,\n\t\t\t\t// so delete it from the local key and\n\t\t\t\t// store with the \"cloud\" type key, and then use that one.\n\t\t\t\t// Otherwise it's a local session under the local key, so just return it.\n\t\t\t\tif (session.expiresAt != null) {\n\t\t\t\t\tcloudIfMissing = true;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait this.deleteSecrets(id, session.id);\n\t\t\t\t\t\tawait this.writeSecret(id, session);\n\t\t\t\t\t} catch {}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If no local session we try to restore a session with the cloud key\n\t\t\tif (session == null && descriptor.cloud !== false) {\n\t\t\t\tcloudIfMissing = true;\n\t\t\t\tsession = await this.readSecret(id, sessionId, true);\n\t\t\t}\n\n\t\t\treturn convertStoredSessionToSession(session, descriptor, cloudIfMissing);\n\t\t});\n\t}\n\n\t/**\n\t * Deletes one connection's stored session. `signOut` is for a delete that signs the integration out (a forced new\n\t * session): it also refuses the store of any token of the provider, or of the descriptor's self-managed host,\n\t * fetched before it (see {@link getSignOutMark}). A cleanup of a replaced token leaves it unset.\n\t */\n\tdeleteStoredSessions(\n\t\tid: IntegrationIds,\n\t\tdescriptor: IntegrationAuthenticationSessionDescriptor,\n\t\tcloud?: boolean,\n\t\toptions?: { preserveConfigured?: boolean; signOut?: boolean },\n\t): Promise<void> {\n\t\treturn this.withLock(id, async () => {\n\t\t\tif (options?.signOut) {\n\t\t\t\tthis.markSignOut(\n\t\t\t\t\tisSelfManagedHostIntegrationId(id) && descriptor.domain\n\t\t\t\t\t\t? this.getHostScope(id, descriptor.domain)\n\t\t\t\t\t\t: id,\n\t\t\t\t);\n\t\t\t}\n\t\t\tawait this.deleteSecrets(id, this.resolveConnectionId(id, descriptor), cloud, options);\n\t\t});\n\t}\n\n\t/** Signs out of every stored session of the provider, or of one self-managed host when `domain` is given. */\n\tdeleteAllStoredSessions(id: IntegrationIds, cloud?: boolean, domain?: string): Promise<void> {\n\t\treturn this.withLock(id, async () => {\n\t\t\tthis.markSignOut(isSelfManagedHostIntegrationId(id) && domain != null ? this.getHostScope(id, domain) : id);\n\t\t\tawait this.deleteAllSecrets(id, cloud, domain);\n\t\t});\n\t}\n\n\t/**\n\t * Reclaims all stored configuration + secrets for the given (typically retired) integration ids.\n\t * Used to clean up state left behind when an id is removed from the model — e.g. the local\n\t * self-managed `github-enterprise`/`gitlab-self-hosted` ids dropped when integrations went cloud-only.\n\t * Domains are read from the stored config (secrets are keyed by domain); ids with no stored config\n\t * are a no-op.\n\t */\n\tasync purgeStoredConfiguration(ids: readonly string[]): Promise<void> {\n\t\tconst stored =\n\t\t\tthis.ctx.storage.get<Record<string, StoredConfiguredIntegrationDescriptor[] | undefined>>(\n\t\t\t\t'integrations:configured',\n\t\t\t);\n\t\tif (stored == null) return;\n\n\t\tlet changed = false;\n\t\tfor (const id of ids) {\n\t\t\tif (!(id in stored)) continue;\n\n\t\t\tfor (const descriptor of stored[id] ?? []) {\n\t\t\t\t// Mirror the hydration backfill so the secret keys we delete match what was written: fall back\n\t\t\t\t// through domain, the provider's canonical domain, then the integration id (never empty). A\n\t\t\t\t// legacy cloud descriptor stored neither id nor domain, so an empty connection id here would\n\t\t\t\t// miss the canonical-domain secret (e.g. `integration.auth.cloud:github|github.com`) and orphan it.\n\t\t\t\tconst connectionId =\n\t\t\t\t\tdescriptor.id || descriptor.domain || providersMetadata[id as IntegrationIds]?.domain || id;\n\t\t\t\tawait this.ctx.storage.deleteSecret(this.getLocalSecretKey(id as IntegrationIds, connectionId));\n\t\t\t\tawait this.ctx.storage.deleteSecret(this.getCloudSecretKey(id as IntegrationIds, connectionId));\n\t\t\t\tif (descriptor.domain) {\n\t\t\t\t\tawait this.ctx.storage.deleteWorkspace(`connected:${id}:${descriptor.domain}`);\n\t\t\t\t}\n\t\t\t}\n\t\t\tchanged = true;\n\t\t}\n\t\tif (!changed) return;\n\n\t\tconst remaining = Object.fromEntries(Object.entries(stored).filter(([key]) => !ids.includes(key)));\n\t\tawait this.ctx.storage.store('integrations:configured', remaining as StoredIntegrationConfigurations);\n\t}\n\n\tprivate async deleteSecrets(\n\t\tid: IntegrationIds,\n\t\tconnectionId: string,\n\t\tcloud?: boolean,\n\t\toptions?: { preserveConfigured?: boolean },\n\t): Promise<void> {\n\t\tif (cloud == null || cloud === false) {\n\t\t\tawait this.ctx.storage.deleteSecret(this.getLocalSecretKey(id, connectionId));\n\t\t}\n\n\t\tif (cloud == null || cloud === true) {\n\t\t\tawait this.ctx.storage.deleteSecret(this.getCloudSecretKey(id, connectionId));\n\t\t}\n\n\t\tif (options?.preserveConfigured) return;\n\n\t\tawait this.removeConfigured(id, { connectionId: connectionId, cloud: cloud });\n\t}\n\n\tprivate async deleteAllSecrets(id: IntegrationIds, cloud?: boolean, domain?: string): Promise<void> {\n\t\t// Delete every connection's secret (multi-account): secrets are keyed per connection id, so a\n\t\t// single canonical-domain delete would orphan secondary tokens. When a domain is given (self-managed\n\t\t// disconnect of one host), scope to that host so other hosts under the same provider id survive.\n\t\tconst descriptors = this.configured.get(id);\n\t\tconst connectionIds = [\n\t\t\t...new Set(\n\t\t\t\t(domain != null ? descriptors?.filter(c => this.domainsMatch(id, c.domain, domain)) : descriptors)?.map(\n\t\t\t\t\tc => c.id,\n\t\t\t\t) ?? [],\n\t\t\t),\n\t\t];\n\t\tif (connectionIds.length) {\n\t\t\tfor (const connectionId of connectionIds) {\n\t\t\t\tawait this.deleteSecrets(id, connectionId, cloud);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\t// A domain-scoped clear that matched nothing means this host has no stored connections, so it must be\n\t\t// a no-op. The canonical-domain fallback below would target a bogus key (self-managed canonical domain\n\t\t// is empty), so skip it.\n\t\tif (domain != null) return;\n\n\t\t// No configured connections (e.g. an orphaned secret with no descriptor): fall back to the\n\t\t// provider's canonical domain, which is the legacy session id for cloud providers. Mirror the\n\t\t// hydration backfill's `|| id` guard so a self-managed provider (empty canonical domain) doesn't\n\t\t// target an ambiguous empty connection id.\n\t\tawait this.deleteSecrets(id, providersMetadata[id]?.domain || id, cloud);\n\t}\n\n\tprivate async writeSecret(\n\t\tid: IntegrationIds,\n\t\tsession: ProviderAuthenticationSession | StoredSession,\n\t\tresource?: ConnectionResource,\n\t): Promise<void> {\n\t\tawait this.ctx.storage.storeSecret(\n\t\t\tthis.getSecretKey(id, session.id, session.cloud ?? false),\n\t\t\tJSON.stringify(session),\n\t\t);\n\n\t\tawait this.addOrUpdateConfigured({\n\t\t\tid: session.id,\n\t\t\tintegrationId: id,\n\t\t\tdomain: isSelfManagedHostIntegrationId(id) ? session.domain : undefined,\n\t\t\tbaseUrl: isSelfManagedHostIntegrationId(id) ? session.baseUrl : undefined,\n\t\t\texpiresAt: session.expiresAt,\n\t\t\tscopes: session.scopes.join(','),\n\t\t\tcloud: session.cloud ?? false,\n\t\t\ttype: session.type,\n\t\t\taccountName: session.account?.label || undefined,\n\t\t\tresourceName: resource?.name,\n\t\t\tresourceId: resource?.id,\n\t\t});\n\t}\n\n\tprivate async readSecret(\n\t\tid: IntegrationIds,\n\t\tsessionId: string,\n\t\tcloud: boolean = false,\n\t): Promise<StoredSession | undefined> {\n\t\tlet storedSession: StoredSession | undefined;\n\t\ttry {\n\t\t\tconst sessionJSON = await this.ctx.storage.getSecret(this.getSecretKey(id, sessionId, cloud));\n\t\t\tif (sessionJSON) {\n\t\t\t\tstoredSession = JSON.parse(sessionJSON);\n\t\t\t\tif (storedSession != null) {\n\t\t\t\t\tconst configured = this.configured.get(id);\n\t\t\t\t\tconst connectionId = storedSession.id ?? sessionId;\n\t\t\t\t\tconst sessionCloud = storedSession.cloud ?? cloud;\n\t\t\t\t\tconst domain = isSelfManagedHostIntegrationId(id)\n\t\t\t\t\t\t? (storedSession.domain ?? storedSession.id)\n\t\t\t\t\t\t: undefined;\n\t\t\t\t\tif (\n\t\t\t\t\t\tconfigured == null ||\n\t\t\t\t\t\tconfigured.length === 0 ||\n\t\t\t\t\t\t!configured.some(\n\t\t\t\t\t\t\tc => c.id === connectionId && c.integrationId === id && c.cloud === sessionCloud,\n\t\t\t\t\t\t)\n\t\t\t\t\t) {\n\t\t\t\t\t\tawait this.addOrUpdateConfigured({\n\t\t\t\t\t\t\tid: connectionId,\n\t\t\t\t\t\t\tintegrationId: id,\n\t\t\t\t\t\t\tdomain: domain,\n\t\t\t\t\t\t\t// Rebuilt from the secret, so it must carry the address the session does; omitting it\n\t\t\t\t\t\t\t// leaves the descriptor claiming no context path and makes reconcile read every\n\t\t\t\t\t\t\t// routine check-in as a re-pointed connection.\n\t\t\t\t\t\t\tbaseUrl: isSelfManagedHostIntegrationId(id) ? storedSession.baseUrl : undefined,\n\t\t\t\t\t\t\texpiresAt: storedSession.expiresAt,\n\t\t\t\t\t\t\tscopes: storedSession.scopes.join(','),\n\t\t\t\t\t\t\tcloud: sessionCloud,\n\t\t\t\t\t\t\ttype: storedSession.type,\n\t\t\t\t\t\t\taccountName: storedSession.account?.label || undefined,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (_ex) {\n\t\t\ttry {\n\t\t\t\tawait this.deleteSecrets(id, sessionId, cloud);\n\t\t\t} catch {}\n\t\t}\n\t\treturn storedSession;\n\t}\n\n\tprivate getSecretKey(\n\t\tid: IntegrationIds,\n\t\tsessionId: string,\n\t\tcloud: boolean = false,\n\t): `integration.auth:${IntegrationIds}|${string}` | `integration.auth.cloud:${IntegrationIds}|${string}` {\n\t\treturn cloud ? this.getCloudSecretKey(id, sessionId) : this.getLocalSecretKey(id, sessionId);\n\t}\n\n\tprivate getLocalSecretKey(id: IntegrationIds, sessionId: string): `integration.auth:${IntegrationIds}|${string}` {\n\t\treturn `integration.auth:${id}|${sessionId}`;\n\t}\n\n\tprivate getCloudSecretKey(\n\t\tid: IntegrationIds,\n\t\tsessionId: string,\n\t): `integration.auth.cloud:${IntegrationIds}|${string}` {\n\t\treturn `integration.auth.cloud:${id}|${sessionId}`;\n\t}\n\n\tprivate getPrimaryScope(\n\t\tid: IntegrationIds,\n\t\tdescriptors: ConfiguredIntegrationDescriptor[],\n\t\tdomain: string | undefined,\n\t): ConfiguredIntegrationDescriptor[] {\n\t\treturn isSelfManagedHostIntegrationId(id)\n\t\t\t? descriptors.filter(d => this.isInPrimaryScope(id, d, domain))\n\t\t\t: descriptors;\n\t}\n\n\tprivate isInPrimaryScope(\n\t\tid: IntegrationIds,\n\t\tdescriptor: ConfiguredIntegrationDescriptor,\n\t\tdomain: string | undefined,\n\t): boolean {\n\t\treturn !isSelfManagedHostIntegrationId(id) || this.domainsMatch(id, descriptor.domain, domain);\n\t}\n\n\t/**\n\t * Resolves the connection id used as the secret-key session id for an auth descriptor.\n\t * - If the descriptor targets a specific connection (`connectionId`), that wins.\n\t * - Otherwise returns the primary connection's id for the provider (matching the descriptor's domain\n\t * for self-managed hosts; any connection for cloud hosts, where the stored domain is undefined).\n\t * - Falls back to the descriptor domain when nothing is configured yet, preserving legacy\n\t * (pre-multi-account) reads with zero secret migration.\n\t */\n\tresolveConnectionId(id: IntegrationIds, descriptor: IntegrationAuthenticationSessionDescriptor): string {\n\t\t// An empty connectionId is not a real target — treat it as \"no target\" so it resolves the primary\n\t\t// rather than keying a secret under an empty id.\n\t\tif (descriptor.connectionId) return descriptor.connectionId;\n\n\t\tconst domain = isSelfManagedHostIntegrationId(id) ? descriptor.domain : undefined;\n\t\tconst candidates = this.scopeConnectionCandidates(id, domain, descriptor.cloud);\n\t\treturn (candidates?.find(c => c.primary) ?? candidates?.[0])?.id ?? descriptor.domain;\n\t}\n\n\t/**\n\t * Returns the id of the configured connection an unscoped descriptor resolves to (the primary for the\n\t * descriptor's domain, matching {@link resolveConnectionId}'s selection), or `undefined` when nothing is\n\t * configured for it. Unlike {@link resolveConnectionId} this only returns a genuine per-connection cloud\n\t * token id (never a local/PAT or domain-derived legacy id), so callers can safely use it to scope a cloud\n\t * token fetch to one host of a multi-host self-managed provider, or fall through to the provider-global\n\t * primary endpoint on `undefined`.\n\t */\n\t/**\n\t * The address already stored for a self-managed connection — see {@link ConfiguredIntegrationDescriptor.baseUrl}.\n\t *\n\t * Exists so a session rebuilt from a backend response that omits the domain can keep the address the\n\t * connection was configured with, rather than silently falling back to the bare host and losing a context\n\t * path the user never changed. Looked up by connection id first, then by host for an unscoped fetch.\n\t */\n\t/**\n\t * Whether `connectionId` names a cloud connection configured for `domain`'s host.\n\t *\n\t * The caller-facing question is \"is this id evidence that a token belongs to this host\". A connection id\n\t * can arrive from a caller rather than from our own configuration, so it is only evidence once it matches\n\t * a descriptor we stored for that host — see the host guard in `CloudIntegrationAuthenticationProvider`.\n\t */\n\tisConnectionConfiguredForHost(\n\t\tid: IntegrationIds,\n\t\tconnectionId: string | undefined,\n\t\tdomain: string | undefined,\n\t): boolean {\n\t\tif (connectionId == null) return false;\n\n\t\tconst connection = this.getConfigured(id, { cloud: true }).find(c => c.id === connectionId);\n\t\tif (connection == null) return false;\n\n\t\treturn !isSelfManagedHostIntegrationId(id) || this.domainsMatch(id, connection.domain, domain);\n\t}\n\n\tgetConfiguredBaseUrl(id: IntegrationIds, connectionId: string | undefined, domain?: string): string | undefined {\n\t\tif (!isSelfManagedHostIntegrationId(id)) return undefined;\n\n\t\tconst configured = this.getConfigured(id, { cloud: true });\n\t\tconst byId = connectionId != null ? configured.find(c => c.id === connectionId) : undefined;\n\t\tif (byId != null) return byId.baseUrl;\n\n\t\treturn configured.find(c => this.domainsMatch(id, c.domain, domain))?.baseUrl;\n\t}\n\n\tgetConfiguredConnectionId(id: IntegrationIds, domain: string | undefined, cloud?: boolean): string | undefined {\n\t\tconst scoped = isSelfManagedHostIntegrationId(id) ? domain : undefined;\n\t\tconst candidates = this.scopeConnectionCandidates(id, scoped, cloud);\n\t\tconst connection = candidates?.find(c => c.primary) ?? candidates?.[0];\n\t\tif (connection == null) return undefined;\n\n\t\t// Only return a real per-connection cloud token id. Reject a local (PAT) descriptor (surfaced by\n\t\t// scopeConnectionCandidates' non-cloud fallback) and a domain-derived legacy id (the descriptor's own\n\t\t// domain or the provider's canonical domain — see ConfiguredIntegrationDescriptor.id), either of which\n\t\t// would target `v1/provider-tokens/tokens/{domain}` (rejected as a non-uuid). Callers then fall through\n\t\t// to the provider-scoped primary endpoint.\n\t\tif (!connection.cloud) return undefined;\n\n\t\tconst canonicalDomain = providersMetadata[id]?.domain;\n\t\tif (connection.id === connection.domain || (canonicalDomain && connection.id === canonicalDomain)) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn connection.id;\n\t}\n\n\t/**\n\t * Selects configured descriptors for a provider matching `domain`, further narrowed to the `cloud`\n\t * variant when specified. A connection id can have both a local (PAT) and cloud descriptor whose ids\n\t * differ (e.g. a legacy local descriptor keyed by domain alongside a real cloud token id); scoping by\n\t * `cloud` keeps a cloud-scoped read/delete from resolving the local id (and vice versa). Falls back to\n\t * the domain-only set when no variant matches, so legacy single-variant resolution is unchanged.\n\t */\n\tprivate scopeConnectionCandidates(\n\t\tid: IntegrationIds,\n\t\tdomain: string | undefined,\n\t\tcloud: boolean | undefined,\n\t): ConfiguredIntegrationDescriptor[] | undefined {\n\t\tconst candidates = this.configured.get(id)?.filter(c => this.domainsMatch(id, c.domain, domain));\n\t\tif (cloud == null || candidates == null) return candidates;\n\n\t\tconst scoped = candidates.filter(c => c.cloud === cloud);\n\t\treturn scoped.length ? scoped : candidates;\n\t}\n\n\t/**\n\t * Marks the given connection as the primary/default for the provider and clears the flag on its\n\t * siblings. Persists immediately instead of relying on a session re-store to carry the primary flag.\n\t */\n\tsetPrimaryConnection(id: IntegrationIds, connectionId: string): Promise<void> {\n\t\treturn this.withLock(id, () => this.setPrimaryConnectionCore(id, connectionId));\n\t}\n\n\tprivate async setPrimaryConnectionCore(id: IntegrationIds, connectionId: string): Promise<void> {\n\t\tconst descriptors = this.configured.get(id);\n\t\tif (descriptors == null || descriptors.length === 0) return;\n\t\tif (!descriptors.some(d => d.id === connectionId)) return;\n\n\t\tconst target =\n\t\t\tdescriptors.find(d => d.id === connectionId && d.cloud) ?? descriptors.find(d => d.id === connectionId);\n\t\tif (target == null) return;\n\n\t\tconst domain = isSelfManagedHostIntegrationId(id) ? target.domain : undefined;\n\t\t// A connection id can have both a local (PAT) and cloud descriptor. Mark the primary on a single\n\t\t// canonical variant (prefer cloud, since multi-account primaries are cloud-driven) within the\n\t\t// provider/host scope, so other self-managed hosts keep their own default connection.\n\t\tconst primaryIsCloud = descriptors.some(\n\t\t\td => d.id === connectionId && d.cloud && this.isInPrimaryScope(id, d, domain),\n\t\t);\n\n\t\tlet changed = false;\n\t\tconst updated = descriptors.map(d => {\n\t\t\tif (!this.isInPrimaryScope(id, d, domain)) return d;\n\n\t\t\tconst primary = d.id === connectionId && (d.cloud ?? false) === primaryIsCloud;\n\t\t\tif ((d.primary ?? false) === primary) return d;\n\n\t\t\tchanged = true;\n\t\t\treturn { ...d, primary: primary };\n\t\t});\n\t\tif (!changed) return;\n\n\t\tthis.configured.set(id, updated);\n\t\tthis.fireChange(id);\n\t\tawait this.storeConfigured();\n\t}\n\n\t/**\n\t * Removes a single connection (its secret + configured descriptor). If it was the primary and other\n\t * connections remain, a secondary is promoted (see {@link removeConfigured}). Unlike\n\t * {@link deleteAllStoredSessions}, this only affects the targeted connection. Pass `cloud` to scope\n\t * the removal to the cloud/local variant when a local PAT and a cloud session share a connection id.\n\t */\n\tdeleteConnection(id: IntegrationIds, connectionId: string, cloud?: boolean): Promise<void> {\n\t\treturn this.withLock(id, async () => {\n\t\t\t// The connection is gone, so a token of it fetched before must not be stored back.\n\t\t\tthis.markSignOut(`${id}|connection:${connectionId}`);\n\t\t\tawait this.deleteSecrets(id, connectionId, cloud);\n\t\t});\n\t}\n\n\tprivate _addedIds = new Set<IntegrationIds>();\n\tprivate _removedIds = new Set<IntegrationIds>();\n\tprivate _fireChangeDebounced?: () => void;\n\n\tprivate normalizeConfiguredDomain(id: IntegrationIds, domain: string | undefined): string | undefined {\n\t\tif (!isSelfManagedHostIntegrationId(id)) return domain;\n\n\t\treturn hostFromDomain(domain) ?? domain;\n\t}\n\n\tprivate domainsMatch(id: IntegrationIds, first: string | undefined, second: string | undefined): boolean {\n\t\tif (first === second) return true;\n\t\tif (!isSelfManagedHostIntegrationId(id)) return false;\n\t\tif (first == null || second == null) return false;\n\n\t\treturn areDomainsOnSameHost(first, second);\n\t}\n\n\tprivate fireChange(added?: IntegrationIds, removed?: IntegrationIds) {\n\t\tthis._fireChangeDebounced ??= debounce(() => {\n\t\t\tconst added = [...this._addedIds];\n\t\t\tthis._addedIds.clear();\n\t\t\tconst removed = [...this._removedIds];\n\t\t\tthis._removedIds.clear();\n\n\t\t\tthis._onDidChange.fire({ added: added, removed: removed });\n\t\t}, 250);\n\n\t\tif (added != null) {\n\t\t\tthis._addedIds.add(added);\n\t\t}\n\t\tif (removed != null) {\n\t\t\tthis._removedIds.add(removed);\n\t\t}\n\t\tthis._fireChangeDebounced();\n\t}\n}\n\nfunction convertStoredSessionToSession(\n\tstoredSession: StoredSession | undefined,\n\tdescriptor: IntegrationAuthenticationSessionDescriptor,\n\tcloudIfMissing: boolean,\n): ProviderAuthenticationSession | undefined {\n\tif (storedSession == null) return undefined;\n\n\treturn {\n\t\tid: storedSession.id,\n\t\taccessToken: storedSession.accessToken,\n\t\taccount: {\n\t\t\tid: storedSession.account?.id ?? '',\n\t\t\tlabel: storedSession.account?.label ?? '',\n\t\t},\n\t\tscopes: storedSession.scopes,\n\t\tcloud: storedSession.cloud ?? cloudIfMissing,\n\t\texpiresAt: storedSession.expiresAt ? new Date(storedSession.expiresAt) : undefined,\n\t\tdomain: storedSession.domain ?? descriptor.domain,\n\t\tbaseUrl: getStoredBaseUrl(storedSession.baseUrl, storedSession.domain, storedSession.protocol),\n\t\tprotocol: storedSession.protocol,\n\t\ttype: storedSession.type,\n\t\t// Carried for providers whose client needs an app key alongside the token (e.g. Trello); without\n\t\t// this a rehydrated session silently loses the key and every read no-ops.\n\t\tappKey: storedSession.appKey,\n\t};\n}\n\nfunction getStoredBaseUrl(\n\tbaseUrl: string | undefined,\n\tdomain: string | undefined,\n\tprotocol?: string,\n): string | undefined {\n\tif (baseUrl != null) return baseUrl;\n\n\tconst legacyUrl = baseUrlFromDomain(domain, protocol);\n\treturn legacyUrl != null && new URL(legacyUrl).pathname !== '/' ? legacyUrl : undefined;\n}\n"],"mappings":";;;;;;;AAgDA,IAAa,+BAAb,MAAgE;CAiBlC;CAhB7B,eAAgC,IAAI,QAA2C;CAC/E,uBAA8C,QAAQ,QAAQ;;;;;;CAM9D,yBAA0B,IAAI,IAAmC;;CAEjE,gBAAwB;;CAExB,4BAA6B,IAAI,IAAoB;CACrD,IAAI,cAAwD;EAC3D,OAAO,KAAK,aAAa;CAC1B;CAEA,YAAY,KAAiD;EAAhC,KAAA,MAAA;CAAiC;CAE9D,UAAgB;EACf,KAAK,aAAa,QAAQ;CAC3B;CAEA;CACA,IAAY,aAAqE;EAChF,IAAI,KAAK,eAAe,MAAM;GAC7B,KAAK,8BAAc,IAAI,IAAuD;GAE9E,MAAM,mBAAmB,KAAK,IAAI,QAAQ,IAAI,yBAAyB;GACvE,KAAK,MAAM,CAAC,IAAI,eAAe,OAAO,QAAQ,oBAAoB,CAAC,CAAC,GAG/D;IACJ,IAAI,cAAc,MAAM;IAExB,MAAM,cAAc,WAAW,KAAI,OAAM;KACxC,GAAG;KACH,SAAS,+BAA+B,EAAE,IAAI,iBAAiB,EAAE,SAAS,EAAE,MAAM,IAAI,EAAE;KACxF,QAAQ,KAAK,0BAA0B,IAAI,EAAE,MAAM;KAOnD,IAAI,EAAE,MAAM,EAAE,UAAU,kBAAkB,GAAG,EAAE,UAAU;KACzD,WAAW,EAAE,YAAY,IAAI,KAAK,EAAE,SAAS,IAAI,KAAA;IAClD,EAAE;IACF,KAAK,YAAY,IAAI,IAAI,WAAW;GACrC;EACD;EAEA,OAAO,KAAK;CACb;CAIA,cACC,IACA,SACoC;EACpC,MAAM,cAAiD,CAAC;EAExD,MAAM,aACL,MAAM,OACH,KAAK,WAAW,IAAI,EAAE,IACtB,CAAC,GAAG,QAAyC,KAAK,WAAW,OAAO,CAAC,CAAC;EAC1E,IAAI,CAAC,YAAY,QAAQ,OAAO;EAEhC,IAAI,SAAS,UAAU,QAAQ,SAAS,SAAS,MAChD,KAAK,MAAM,cAAc,YAAY;GACpC,IACE,SAAS,UAAU,QACnB,CAAC,KAAK,aAAa,MAAM,WAAW,eAAe,WAAW,QAAQ,QAAQ,MAAM,KACpF,SAAS,UAAU,QAAQ,CAAC,WAAW,SACvC,SAAS,UAAU,SAAS,WAAW,OAExC;GAGD,YAAY,KAAK,UAAU;EAC5B;OAEA,YAAY,KAAK,GAAG,UAAU;EAG/B,OAAO;CACR;CAEA,MAAc,kBAAiC;EAE9C,MAAM,aAA8C,CAAC;EACrD,KAAK,MAAM,CAAC,IAAI,gBAAgB,KAAK,YACpC,WAAW,MAAM,YAAY,KAAI,OAAM;GACtC,GAAG;GACH,WAAW,EAAE,YACV,EAAE,qBAAqB,OACtB,EAAE,UAAU,YAAY,IACxB,EAAE,YACH,KAAA;EACJ,EAAE;EAGH,MAAM,UAAU,KAAK,qBAAqB,WACzC,KAAK,IAAI,QAAQ,MAAM,2BAA2B,UAAU,CAC7D;EACA,KAAK,uBAAuB,QAAQ,YAAY,CAAC,CAAC;EAClD,MAAM;CACP;CAEA,MAAc,sBAAsB,YAA4D;EAC/F,aAAa;GACZ,GAAG;GACH,SAAS,+BAA+B,WAAW,aAAa,IAC7D,iBAAiB,WAAW,SAAS,WAAW,MAAM,IACtD,WAAW;GACd,QAAQ,KAAK,0BAA0B,WAAW,eAAe,WAAW,MAAM;EACnF;EACA,MAAM,cAAc,KAAK,WAAW,IAAI,WAAW,aAAa,KAAK,CAAC;EAGtE,MAAM,WAAW,YAAY,MAAK,MAAK,EAAE,OAAO,WAAW,MAAM,EAAE,UAAU,WAAW,KAAK;EAK7F,MAAM,eAAe,KAAK,gBAAgB,WAAW,eAAe,aAAa,WAAW,MAAM;EAClG,MAAM,UAAU,WAAW,WAAW,UAAU,WAAW,CAAC,aAAa,MAAK,MAAK,EAAE,OAAO;EAG5F,MAAM,OAAO,WAAW,QAAQ,UAAU;EAC1C,MAAM,cAAc,WAAW,eAAe,UAAU;EAExD,MAAM,WAAW,WAAW,cAAc,OAAO,aAAa;EAC9D,MAAM,aAA8C;GACnD,GAAG;GACM;GACH;GACO;GACb,cAAc,UAAU;GACxB,YAAY,UAAU;EACvB;EAEA,IAAI;EACJ,IAAI,YAAY,MAAM;GAKrB,IACC,SAAS,WAAW,WAAW,UAC/B,sBAAsB,SAAS,SAAS,WAAW,OAAO,KAC1D,SAAS,cAAc,WAAW,aAClC,SAAS,WAAW,WAAW,WAC9B,SAAS,WAAW,YAAY,WAAW,WAAW,UACvD,SAAS,SAAS,WAAW,QAC7B,SAAS,gBAAgB,WAAW,eACpC,SAAS,iBAAiB,WAAW,gBACrC,SAAS,eAAe,WAAW,YAEnC;GAID,UACC,SAAS,WAAW,WAAW,UAC/B,CAAC,sBAAsB,SAAS,SAAS,WAAW,OAAO,KAC3D,SAAS,WAAW,WAAW,WAC9B,SAAS,WAAW,YAAY,WAAW,WAAW,UACvD,SAAS,SAAS,WAAW,QAC7B,SAAS,gBAAgB,WAAW,eACpC,SAAS,iBAAiB,WAAW,gBACrC,SAAS,eAAe,WAAW;GAGpC,YAAY,OAAO,YAAY,QAAQ,QAAQ,GAAG,CAAC;EACpD,OACC,UAAU;EAGX,YAAY,KAAK,UAAU;EAC3B,KAAK,WAAW,IAAI,WAAW,eAAe,WAAW;EAEzD,IAAI,SACH,KAAK,WAAW,WAAW,aAAa;EAEzC,MAAM,KAAK,gBAAgB;CAC5B;CAEA,MAAc,iBACb,IACA,SACgB;EAChB,MAAM,WAAW,KAAK,WAAW,IAAI,EAAE;EACvC,IAAI,YAAY,QAAQ,SAAS,WAAW,GAAG;EAE/C,MAAM,wCAAwB,IAAI,IAAwB;EAC1D,MAAM,cAAiD,CAAC;EACxD,KAAK,MAAM,KAAK,UAAU;GACzB,IACC,EAAE,OAAO,QAAQ,iBAChB,SAAS,SAAS,QACjB,SAAS,UAAU,QAAQ,EAAE,UAAU,QACvC,SAAS,UAAU,SAAS,EAAE,UAAU,QACzC;IACD,IAAI,EAAE,SACL,sBAAsB,IAAI,EAAE,MAAM;IAEnC;GACD;GAEA,YAAY,KAAK,CAAC;EACnB;EAEA,IAAI,YAAY,WAAW,SAAS,QAAQ;EAI5C,KAAK,MAAM,UAAU,uBAAuB;GAC3C,IAAI,YAAY,MAAK,MAAK,KAAK,iBAAiB,IAAI,GAAG,MAAM,KAAK,EAAE,OAAO,GAAG;GAE9E,MAAM,QAAQ,YAAY,WAAU,MAAK,KAAK,iBAAiB,IAAI,GAAG,MAAM,CAAC;GAC7E,IAAI,UAAU,IACb,YAAY,SAAS;IAAE,GAAG,YAAY;IAAQ,SAAS;GAAK;EAE9D;EAEA,KAAK,WAAW,IAAI,IAAI,WAAW;EACnC,KAAK,WAAW,KAAA,GAAW,EAAE;EAC7B,MAAM,KAAK,gBAAgB;CAC5B;CAEA,SAAoB,IAAoB,IAAkC;EACzE,MAAM,OAAO,KAAK,OAAO,IAAI,EAAE,KAAK,QAAQ,QAAQ,EAAA,CAAG,KAAK,EAAE;EAC9D,MAAM,UAAU,IAAI,WACb,KAAA,SACA,KAAA,CACP;EACA,KAAK,OAAO,IAAI,IAAI,OAAO;EAC3B,QAAa,WAAW;GACvB,IAAI,KAAK,OAAO,IAAI,EAAE,MAAM,SAC3B,KAAK,OAAO,OAAO,EAAE;EAEvB,CAAC;EACD,OAAO;CACR;;;;;;CAOA,iBAAyB;EACxB,OAAO,KAAK;CACb;CAEA,YAAoB,OAAqB;EACxC,KAAK,UAAU,IAAI,OAAO,EAAE,KAAK,aAAa;CAC/C;CAEA,aAAqB,IAAoB,QAAwB;EAChE,OAAO,GAAG,GAAG,QAAQ,eAAe,MAAM,KAAK;CAChD;CAEA,iBAAyB,IAAoB,SAAwC,MAAuB;EAC3G,MAAM,SAAS,WAAmB,KAAK,UAAU,IAAI,KAAK,KAAK,KAAK;EACpE,IAAI,MAAM,EAAE,GAAG,OAAO;EACtB,IAAI,+BAA+B,EAAE,KAAK,QAAQ,UAAU,MAAM,KAAK,aAAa,IAAI,QAAQ,MAAM,CAAC,GACtG,OAAO;EAER,OAAO,MAAM,GAAG,GAAG,cAAc,QAAQ,IAAI;CAC9C;;;;;CAMA,aACC,IACA,SACA,SACmB;EACnB,OAAO,KAAK,SAAS,IAAI,YAAY;GACpC,IAAI,SAAS,eAAe,QAAQ,KAAK,iBAAiB,IAAI,SAAS,QAAQ,WAAW,GAAG,OAAO;GAEpG,MAAM,KAAK,YAAY,IAAI,SAAS,SAAS,QAAQ;GACrD,OAAO;EACR,CAAC;CACF;CAEA,iBACC,IACA,YACqD;EAErD,OAAO,KAAK,SAAS,IAAI,YAAY;GACpC,MAAM,YAAY,KAAK,oBAAoB,IAAI,UAAU;GACzD,IAAI,UAAU,WAAW,UAAU,OAAO,KAAA,IAAY,MAAM,KAAK,WAAW,IAAI,WAAW,KAAK;GAEhG,IAAI,iBAAiB;GACrB,IAAI,WAAW,MAMV;QAAA,QAAQ,aAAa,MAAM;KAC9B,iBAAiB;KACjB,IAAI;MACH,MAAM,KAAK,cAAc,IAAI,QAAQ,EAAE;MACvC,MAAM,KAAK,YAAY,IAAI,OAAO;KACnC,QAAQ,CAAC;IACV;;GAID,IAAI,WAAW,QAAQ,WAAW,UAAU,OAAO;IAClD,iBAAiB;IACjB,UAAU,MAAM,KAAK,WAAW,IAAI,WAAW,IAAI;GACpD;GAEA,OAAO,8BAA8B,SAAS,YAAY,cAAc;EACzE,CAAC;CACF;;;;;;CAOA,qBACC,IACA,YACA,OACA,SACgB;EAChB,OAAO,KAAK,SAAS,IAAI,YAAY;GACpC,IAAI,SAAS,SACZ,KAAK,YACJ,+BAA+B,EAAE,KAAK,WAAW,SAC9C,KAAK,aAAa,IAAI,WAAW,MAAM,IACvC,EACJ;GAED,MAAM,KAAK,cAAc,IAAI,KAAK,oBAAoB,IAAI,UAAU,GAAG,OAAO,OAAO;EACtF,CAAC;CACF;;CAGA,wBAAwB,IAAoB,OAAiB,QAAgC;EAC5F,OAAO,KAAK,SAAS,IAAI,YAAY;GACpC,KAAK,YAAY,+BAA+B,EAAE,KAAK,UAAU,OAAO,KAAK,aAAa,IAAI,MAAM,IAAI,EAAE;GAC1G,MAAM,KAAK,iBAAiB,IAAI,OAAO,MAAM;EAC9C,CAAC;CACF;;;;;;;;CASA,MAAM,yBAAyB,KAAuC;EACrE,MAAM,SACL,KAAK,IAAI,QAAQ,IAChB,yBACD;EACD,IAAI,UAAU,MAAM;EAEpB,IAAI,UAAU;EACd,KAAK,MAAM,MAAM,KAAK;GACrB,IAAI,EAAE,MAAM,SAAS;GAErB,KAAK,MAAM,cAAc,OAAO,OAAO,CAAC,GAAG;IAK1C,MAAM,eACL,WAAW,MAAM,WAAW,UAAU,kBAAkB,GAAqB,EAAE,UAAU;IAC1F,MAAM,KAAK,IAAI,QAAQ,aAAa,KAAK,kBAAkB,IAAsB,YAAY,CAAC;IAC9F,MAAM,KAAK,IAAI,QAAQ,aAAa,KAAK,kBAAkB,IAAsB,YAAY,CAAC;IAC9F,IAAI,WAAW,QACd,MAAM,KAAK,IAAI,QAAQ,gBAAgB,aAAa,GAAG,GAAG,WAAW,QAAQ;GAE/E;GACA,UAAU;EACX;EACA,IAAI,CAAC,SAAS;EAEd,MAAM,YAAY,OAAO,YAAY,OAAO,QAAQ,MAAM,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,GAAG,CAAC,CAAC;EACjG,MAAM,KAAK,IAAI,QAAQ,MAAM,2BAA2B,SAA4C;CACrG;CAEA,MAAc,cACb,IACA,cACA,OACA,SACgB;EAChB,IAAI,SAAS,QAAQ,UAAU,OAC9B,MAAM,KAAK,IAAI,QAAQ,aAAa,KAAK,kBAAkB,IAAI,YAAY,CAAC;EAG7E,IAAI,SAAS,QAAQ,UAAU,MAC9B,MAAM,KAAK,IAAI,QAAQ,aAAa,KAAK,kBAAkB,IAAI,YAAY,CAAC;EAG7E,IAAI,SAAS,oBAAoB;EAEjC,MAAM,KAAK,iBAAiB,IAAI;GAAgB;GAAqB;EAAM,CAAC;CAC7E;CAEA,MAAc,iBAAiB,IAAoB,OAAiB,QAAgC;EAInG,MAAM,cAAc,KAAK,WAAW,IAAI,EAAE;EAC1C,MAAM,gBAAgB,CACrB,GAAG,IAAI,KACL,UAAU,OAAO,aAAa,QAAO,MAAK,KAAK,aAAa,IAAI,EAAE,QAAQ,MAAM,CAAC,IAAI,YAAA,EAAc,KACnG,MAAK,EAAE,EACR,KAAK,CAAC,CACP,CACD;EACA,IAAI,cAAc,QAAQ;GACzB,KAAK,MAAM,gBAAgB,eAC1B,MAAM,KAAK,cAAc,IAAI,cAAc,KAAK;GAGjD;EACD;EAKA,IAAI,UAAU,MAAM;EAMpB,MAAM,KAAK,cAAc,IAAI,kBAAkB,GAAG,EAAE,UAAU,IAAI,KAAK;CACxE;CAEA,MAAc,YACb,IACA,SACA,UACgB;EAChB,MAAM,KAAK,IAAI,QAAQ,YACtB,KAAK,aAAa,IAAI,QAAQ,IAAI,QAAQ,SAAS,KAAK,GACxD,KAAK,UAAU,OAAO,CACvB;EAEA,MAAM,KAAK,sBAAsB;GAChC,IAAI,QAAQ;GACZ,eAAe;GACf,QAAQ,+BAA+B,EAAE,IAAI,QAAQ,SAAS,KAAA;GAC9D,SAAS,+BAA+B,EAAE,IAAI,QAAQ,UAAU,KAAA;GAChE,WAAW,QAAQ;GACnB,QAAQ,QAAQ,OAAO,KAAK,GAAG;GAC/B,OAAO,QAAQ,SAAS;GACxB,MAAM,QAAQ;GACd,aAAa,QAAQ,SAAS,SAAS,KAAA;GACvC,cAAc,UAAU;GACxB,YAAY,UAAU;EACvB,CAAC;CACF;CAEA,MAAc,WACb,IACA,WACA,QAAiB,OACoB;EACrC,IAAI;EACJ,IAAI;GACH,MAAM,cAAc,MAAM,KAAK,IAAI,QAAQ,UAAU,KAAK,aAAa,IAAI,WAAW,KAAK,CAAC;GAC5F,IAAI,aAAa;IAChB,gBAAgB,KAAK,MAAM,WAAW;IACtC,IAAI,iBAAiB,MAAM;KAC1B,MAAM,aAAa,KAAK,WAAW,IAAI,EAAE;KACzC,MAAM,eAAe,cAAc,MAAM;KACzC,MAAM,eAAe,cAAc,SAAS;KAC5C,MAAM,SAAS,+BAA+B,EAAE,IAC5C,cAAc,UAAU,cAAc,KACvC,KAAA;KACH,IACC,cAAc,QACd,WAAW,WAAW,KACtB,CAAC,WAAW,MACX,MAAK,EAAE,OAAO,gBAAgB,EAAE,kBAAkB,MAAM,EAAE,UAAU,YACrE,GAEA,MAAM,KAAK,sBAAsB;MAChC,IAAI;MACJ,eAAe;MACP;MAIR,SAAS,+BAA+B,EAAE,IAAI,cAAc,UAAU,KAAA;MACtE,WAAW,cAAc;MACzB,QAAQ,cAAc,OAAO,KAAK,GAAG;MACrC,OAAO;MACP,MAAM,cAAc;MACpB,aAAa,cAAc,SAAS,SAAS,KAAA;KAC9C,CAAC;IAEH;GACD;EACD,SAAS,KAAK;GACb,IAAI;IACH,MAAM,KAAK,cAAc,IAAI,WAAW,KAAK;GAC9C,QAAQ,CAAC;EACV;EACA,OAAO;CACR;CAEA,aACC,IACA,WACA,QAAiB,OACuF;EACxG,OAAO,QAAQ,KAAK,kBAAkB,IAAI,SAAS,IAAI,KAAK,kBAAkB,IAAI,SAAS;CAC5F;CAEA,kBAA0B,IAAoB,WAAmE;EAChH,OAAO,oBAAoB,GAAG,GAAG;CAClC;CAEA,kBACC,IACA,WACuD;EACvD,OAAO,0BAA0B,GAAG,GAAG;CACxC;CAEA,gBACC,IACA,aACA,QACoC;EACpC,OAAO,+BAA+B,EAAE,IACrC,YAAY,QAAO,MAAK,KAAK,iBAAiB,IAAI,GAAG,MAAM,CAAC,IAC5D;CACJ;CAEA,iBACC,IACA,YACA,QACU;EACV,OAAO,CAAC,+BAA+B,EAAE,KAAK,KAAK,aAAa,IAAI,WAAW,QAAQ,MAAM;CAC9F;;;;;;;;;CAUA,oBAAoB,IAAoB,YAAgE;EAGvG,IAAI,WAAW,cAAc,OAAO,WAAW;EAE/C,MAAM,SAAS,+BAA+B,EAAE,IAAI,WAAW,SAAS,KAAA;EACxE,MAAM,aAAa,KAAK,0BAA0B,IAAI,QAAQ,WAAW,KAAK;EAC9E,QAAQ,YAAY,MAAK,MAAK,EAAE,OAAO,KAAK,aAAa,GAAA,EAAK,MAAM,WAAW;CAChF;;;;;;;;;;;;;;;;;;;;;;;CAwBA,8BACC,IACA,cACA,QACU;EACV,IAAI,gBAAgB,MAAM,OAAO;EAEjC,MAAM,aAAa,KAAK,cAAc,IAAI,EAAE,OAAO,KAAK,CAAC,CAAC,CAAC,MAAK,MAAK,EAAE,OAAO,YAAY;EAC1F,IAAI,cAAc,MAAM,OAAO;EAE/B,OAAO,CAAC,+BAA+B,EAAE,KAAK,KAAK,aAAa,IAAI,WAAW,QAAQ,MAAM;CAC9F;CAEA,qBAAqB,IAAoB,cAAkC,QAAqC;EAC/G,IAAI,CAAC,+BAA+B,EAAE,GAAG,OAAO,KAAA;EAEhD,MAAM,aAAa,KAAK,cAAc,IAAI,EAAE,OAAO,KAAK,CAAC;EACzD,MAAM,OAAO,gBAAgB,OAAO,WAAW,MAAK,MAAK,EAAE,OAAO,YAAY,IAAI,KAAA;EAClF,IAAI,QAAQ,MAAM,OAAO,KAAK;EAE9B,OAAO,WAAW,MAAK,MAAK,KAAK,aAAa,IAAI,EAAE,QAAQ,MAAM,CAAC,CAAC,EAAE;CACvE;CAEA,0BAA0B,IAAoB,QAA4B,OAAqC;EAC9G,MAAM,SAAS,+BAA+B,EAAE,IAAI,SAAS,KAAA;EAC7D,MAAM,aAAa,KAAK,0BAA0B,IAAI,QAAQ,KAAK;EACnE,MAAM,aAAa,YAAY,MAAK,MAAK,EAAE,OAAO,KAAK,aAAa;EACpE,IAAI,cAAc,MAAM,OAAO,KAAA;EAO/B,IAAI,CAAC,WAAW,OAAO,OAAO,KAAA;EAE9B,MAAM,kBAAkB,kBAAkB,GAAG,EAAE;EAC/C,IAAI,WAAW,OAAO,WAAW,UAAW,mBAAmB,WAAW,OAAO,iBAChF;EAED,OAAO,WAAW;CACnB;;;;;;;;CASA,0BACC,IACA,QACA,OACgD;EAChD,MAAM,aAAa,KAAK,WAAW,IAAI,EAAE,CAAC,EAAE,QAAO,MAAK,KAAK,aAAa,IAAI,EAAE,QAAQ,MAAM,CAAC;EAC/F,IAAI,SAAS,QAAQ,cAAc,MAAM,OAAO;EAEhD,MAAM,SAAS,WAAW,QAAO,MAAK,EAAE,UAAU,KAAK;EACvD,OAAO,OAAO,SAAS,SAAS;CACjC;;;;;CAMA,qBAAqB,IAAoB,cAAqC;EAC7E,OAAO,KAAK,SAAS,UAAU,KAAK,yBAAyB,IAAI,YAAY,CAAC;CAC/E;CAEA,MAAc,yBAAyB,IAAoB,cAAqC;EAC/F,MAAM,cAAc,KAAK,WAAW,IAAI,EAAE;EAC1C,IAAI,eAAe,QAAQ,YAAY,WAAW,GAAG;EACrD,IAAI,CAAC,YAAY,MAAK,MAAK,EAAE,OAAO,YAAY,GAAG;EAEnD,MAAM,SACL,YAAY,MAAK,MAAK,EAAE,OAAO,gBAAgB,EAAE,KAAK,KAAK,YAAY,MAAK,MAAK,EAAE,OAAO,YAAY;EACvG,IAAI,UAAU,MAAM;EAEpB,MAAM,SAAS,+BAA+B,EAAE,IAAI,OAAO,SAAS,KAAA;EAIpE,MAAM,iBAAiB,YAAY,MAClC,MAAK,EAAE,OAAO,gBAAgB,EAAE,SAAS,KAAK,iBAAiB,IAAI,GAAG,MAAM,CAC7E;EAEA,IAAI,UAAU;EACd,MAAM,UAAU,YAAY,KAAI,MAAK;GACpC,IAAI,CAAC,KAAK,iBAAiB,IAAI,GAAG,MAAM,GAAG,OAAO;GAElD,MAAM,UAAU,EAAE,OAAO,iBAAiB,EAAE,SAAS,WAAW;GAChE,KAAK,EAAE,WAAW,WAAW,SAAS,OAAO;GAE7C,UAAU;GACV,OAAO;IAAE,GAAG;IAAY;GAAQ;EACjC,CAAC;EACD,IAAI,CAAC,SAAS;EAEd,KAAK,WAAW,IAAI,IAAI,OAAO;EAC/B,KAAK,WAAW,EAAE;EAClB,MAAM,KAAK,gBAAgB;CAC5B;;;;;;;CAQA,iBAAiB,IAAoB,cAAsB,OAAgC;EAC1F,OAAO,KAAK,SAAS,IAAI,YAAY;GAEpC,KAAK,YAAY,GAAG,GAAG,cAAc,cAAc;GACnD,MAAM,KAAK,cAAc,IAAI,cAAc,KAAK;EACjD,CAAC;CACF;CAEA,4BAAoB,IAAI,IAAoB;CAC5C,8BAAsB,IAAI,IAAoB;CAC9C;CAEA,0BAAkC,IAAoB,QAAgD;EACrG,IAAI,CAAC,+BAA+B,EAAE,GAAG,OAAO;EAEhD,OAAO,eAAe,MAAM,KAAK;CAClC;CAEA,aAAqB,IAAoB,OAA2B,QAAqC;EACxG,IAAI,UAAU,QAAQ,OAAO;EAC7B,IAAI,CAAC,+BAA+B,EAAE,GAAG,OAAO;EAChD,IAAI,SAAS,QAAQ,UAAU,MAAM,OAAO;EAE5C,OAAO,qBAAqB,OAAO,MAAM;CAC1C;CAEA,WAAmB,OAAwB,SAA0B;EACpE,KAAK,yBAAyB,eAAe;GAC5C,MAAM,QAAQ,CAAC,GAAG,KAAK,SAAS;GAChC,KAAK,UAAU,MAAM;GACrB,MAAM,UAAU,CAAC,GAAG,KAAK,WAAW;GACpC,KAAK,YAAY,MAAM;GAEvB,KAAK,aAAa,KAAK;IAAS;IAAgB;GAAQ,CAAC;EAC1D,GAAG,GAAG;EAEN,IAAI,SAAS,MACZ,KAAK,UAAU,IAAI,KAAK;EAEzB,IAAI,WAAW,MACd,KAAK,YAAY,IAAI,OAAO;EAE7B,KAAK,qBAAqB;CAC3B;AACD;AAEA,SAAS,8BACR,eACA,YACA,gBAC4C;CAC5C,IAAI,iBAAiB,MAAM,OAAO,KAAA;CAElC,OAAO;EACN,IAAI,cAAc;EAClB,aAAa,cAAc;EAC3B,SAAS;GACR,IAAI,cAAc,SAAS,MAAM;GACjC,OAAO,cAAc,SAAS,SAAS;EACxC;EACA,QAAQ,cAAc;EACtB,OAAO,cAAc,SAAS;EAC9B,WAAW,cAAc,YAAY,IAAI,KAAK,cAAc,SAAS,IAAI,KAAA;EACzE,QAAQ,cAAc,UAAU,WAAW;EAC3C,SAAS,iBAAiB,cAAc,SAAS,cAAc,QAAQ,cAAc,QAAQ;EAC7F,UAAU,cAAc;EACxB,MAAM,cAAc;EAGpB,QAAQ,cAAc;CACvB;AACD;AAEA,SAAS,iBACR,SACA,QACA,UACqB;CACrB,IAAI,WAAW,MAAM,OAAO;CAE5B,MAAM,YAAY,kBAAkB,QAAQ,QAAQ;CACpD,OAAO,aAAa,QAAQ,IAAI,IAAI,SAAS,CAAC,CAAC,aAAa,MAAM,YAAY,KAAA;AAC/E"}
1
+ {"version":3,"file":"configuredIntegrationService.js","names":[],"sources":["../../../../../plus/integrations/src/authentication/configuredIntegrationService.ts"],"sourcesContent":["import { debounce } from '@gitlens/utils/debounce.js';\nimport type { Disposable } from '@gitlens/utils/disposable.js';\nimport type { Event } from '@gitlens/utils/event.js';\nimport { Emitter } from '@gitlens/utils/event.js';\nimport { flatten } from '@gitlens/utils/iterable.js';\nimport type {\n\tIntegrationIds,\n\tStoredConfiguredIntegrationDescriptor,\n\tStoredIntegrationConfigurations,\n} from '../constants.js';\nimport type { IntegrationServiceContext } from '../context.js';\nimport { providersMetadata } from '../providers/models.js';\nimport {\n\tareDomainsOnSameHost,\n\tbaseUrlFromDomain,\n\thostFromDomain,\n\tsameConfiguredBaseUrl,\n} from '../utils/domain.utils.js';\nimport { isSelfManagedHostIntegrationId } from '../utils/integration.utils.js';\nimport type { IntegrationAuthenticationSessionDescriptor } from './integrationAuthenticationProvider.js';\nimport type {\n\tCloudIntegrationAuthType,\n\tConfiguredIntegrationDescriptor,\n\tConnectionResource,\n\tProviderAuthenticationSession,\n} from './models.js';\nimport { getSessionIdentity } from './models.js';\n\ninterface StoredSession {\n\tid: string;\n\taccessToken: string;\n\taccount?: { label?: string; displayName?: string; id: string };\n\tscopes: string[];\n\tcloud?: boolean;\n\ttype: CloudIntegrationAuthType | undefined;\n\texpiresAt?: string;\n\tdomain?: string;\n\t/** See {@link ProviderAuthenticationSession.baseUrl}: the configured address, path included. */\n\tbaseUrl?: string;\n\tprotocol?: string;\n\t/** The provider app key paired with the token for providers whose client needs one (e.g. Trello). */\n\tappKey?: string;\n}\n\nexport interface ConfiguredIntegrationsChangeEvent {\n\treadonly added: readonly IntegrationIds[];\n\treadonly removed: readonly IntegrationIds[];\n}\n\ntype IntegrationSessionChangeEvent = {\n\treadonly integrationId: IntegrationIds;\n\treadonly session: ProviderAuthenticationSession;\n\treadonly previousDomain?: string;\n};\n\nexport class ConfiguredIntegrationService implements Disposable {\n\tprivate readonly _onDidChange = new Emitter<ConfiguredIntegrationsChangeEvent>();\n\tprivate readonly _onWillChangeSession = new Emitter<IntegrationSessionChangeEvent>();\n\tprivate storeConfiguredQueue: Promise<void> = Promise.resolve();\n\t/**\n\t * One provider's secret and descriptor mutations run one at a time, so a sign-out never interleaves with a\n\t * token being stored: storing writes the secret and then registers its descriptor, and a delete in between would\n\t * miss a connection it cannot see yet, or be undone by the pending write (#5948).\n\t */\n\tprivate readonly _locks = new Map<IntegrationIds, Promise<void>>();\n\t/** Monotonic across providers; see {@link getSignOutMark}. */\n\tprivate _signOutEpoch = 0;\n\t/** The epoch of the latest sign-out per scope: a provider, a self-managed host, or a single connection. */\n\tprivate readonly _signOuts = new Map<string, number>();\n\tget onDidChange(): Event<ConfiguredIntegrationsChangeEvent> {\n\t\treturn this._onDidChange.event;\n\t}\n\tget onWillChangeSession(): Event<IntegrationSessionChangeEvent> {\n\t\treturn this._onWillChangeSession.event;\n\t}\n\n\tconstructor(private readonly ctx: IntegrationServiceContext) {}\n\n\tdispose(): void {\n\t\tthis._onDidChange.dispose();\n\t\tthis._onWillChangeSession.dispose();\n\t}\n\n\tprivate _configured?: Map<IntegrationIds, ConfiguredIntegrationDescriptor[]>;\n\tprivate get configured(): Map<IntegrationIds, ConfiguredIntegrationDescriptor[]> {\n\t\tif (this._configured == null) {\n\t\t\tthis._configured = new Map<IntegrationIds, ConfiguredIntegrationDescriptor[]>();\n\n\t\t\tconst storedConfigured = this.ctx.storage.get('integrations:configured');\n\t\t\tfor (const [id, configured] of Object.entries(storedConfigured ?? {}) as [\n\t\t\t\tIntegrationIds,\n\t\t\t\tStoredConfiguredIntegrationDescriptor[],\n\t\t\t][]) {\n\t\t\t\tif (configured == null) continue;\n\n\t\t\t\tconst descriptors = configured.map(d => ({\n\t\t\t\t\t...d,\n\t\t\t\t\tbaseUrl: isSelfManagedHostIntegrationId(id) ? getStoredBaseUrl(d.baseUrl, d.domain) : d.baseUrl,\n\t\t\t\t\tdomain: this.normalizeConfiguredDomain(id, d.domain),\n\t\t\t\t\t// Backfill a stable connection id for pre-multi-account stored data: the domain for\n\t\t\t\t\t// self-managed hosts, or the provider's canonical domain for cloud (which is the legacy\n\t\t\t\t\t// secret-key session id), so existing secrets keep resolving with zero migration. Fall back\n\t\t\t\t\t// to the integration id (never empty) when no domain is known — self-managed providers carry\n\t\t\t\t\t// `domain: ''` in metadata, and an empty id would collide across connections and produce\n\t\t\t\t\t// ambiguous secret keys (`...|`).\n\t\t\t\t\tid: d.id || d.domain || providersMetadata[id]?.domain || id,\n\t\t\t\t\texpiresAt: d.expiresAt ? new Date(d.expiresAt) : undefined,\n\t\t\t\t}));\n\t\t\t\tthis._configured.set(id, descriptors);\n\t\t\t}\n\t\t}\n\n\t\treturn this._configured;\n\t}\n\n\t// Synchronous: reads the in-memory configured map (lazily hydrated from storage). No async work —\n\t// the old async variant only existed to weave in the built-in VS Code GitHub session, which is gone.\n\tgetConfigured(\n\t\tid?: IntegrationIds,\n\t\toptions?: { cloud?: boolean; domain?: string },\n\t): ConfiguredIntegrationDescriptor[] {\n\t\tconst descriptors: ConfiguredIntegrationDescriptor[] = [];\n\n\t\tconst configured =\n\t\t\tid != null\n\t\t\t\t? this.configured.get(id)\n\t\t\t\t: [...flatten<ConfiguredIntegrationDescriptor>(this.configured.values())];\n\t\tif (!configured?.length) return descriptors;\n\n\t\tif (options?.domain != null || options?.cloud != null) {\n\t\t\tfor (const descriptor of configured) {\n\t\t\t\tif (\n\t\t\t\t\t(options?.domain != null &&\n\t\t\t\t\t\t!this.domainsMatch(id ?? descriptor.integrationId, descriptor.domain, options.domain)) ||\n\t\t\t\t\t(options?.cloud === true && !descriptor.cloud) ||\n\t\t\t\t\t(options?.cloud === false && descriptor.cloud)\n\t\t\t\t) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tdescriptors.push(descriptor);\n\t\t\t}\n\t\t} else {\n\t\t\tdescriptors.push(...configured);\n\t\t}\n\n\t\treturn descriptors;\n\t}\n\n\tprivate async storeConfigured(): Promise<void> {\n\t\t// We need to convert the map to a record to store\n\t\tconst configured: StoredIntegrationConfigurations = {} as unknown as StoredIntegrationConfigurations;\n\t\tfor (const [id, descriptors] of this.configured) {\n\t\t\tconfigured[id] = descriptors.map(d => ({\n\t\t\t\t...d,\n\t\t\t\texpiresAt: d.expiresAt\n\t\t\t\t\t? d.expiresAt instanceof Date\n\t\t\t\t\t\t? d.expiresAt.toISOString()\n\t\t\t\t\t\t: d.expiresAt\n\t\t\t\t\t: undefined,\n\t\t\t}));\n\t\t}\n\n\t\tconst pending = this.storeConfiguredQueue.then(() =>\n\t\t\tthis.ctx.storage.store('integrations:configured', configured),\n\t\t);\n\t\tthis.storeConfiguredQueue = pending.catch(() => {});\n\t\tawait pending;\n\t}\n\n\tprivate async addOrUpdateConfigured(descriptor: ConfiguredIntegrationDescriptor): Promise<void> {\n\t\tdescriptor = {\n\t\t\t...descriptor,\n\t\t\tbaseUrl: isSelfManagedHostIntegrationId(descriptor.integrationId)\n\t\t\t\t? getStoredBaseUrl(descriptor.baseUrl, descriptor.domain)\n\t\t\t\t: descriptor.baseUrl,\n\t\t\tdomain: this.normalizeConfiguredDomain(descriptor.integrationId, descriptor.domain),\n\t\t};\n\t\tconst descriptors = this.configured.get(descriptor.integrationId) ?? [];\n\t\t// Key connections by their stable id (+ cloud, to preserve legacy local/cloud coexistence) so\n\t\t// multiple accounts on the same provider+domain no longer overwrite each other.\n\t\tconst existing = descriptors.find(d => d.id === descriptor.id && d.cloud === descriptor.cloud);\n\n\t\t// The first connection for a provider/domain is primary by default; an explicit flag (or the\n\t\t// existing value) always wins. Self-managed providers can span multiple hosts under the same\n\t\t// integration id, so each host needs its own primary.\n\t\tconst primaryScope = this.getPrimaryScope(descriptor.integrationId, descriptors, descriptor.domain);\n\t\tconst primary = descriptor.primary ?? existing?.primary ?? !primaryScope.some(d => d.primary);\n\t\t// Preserve a previously-resolved type/accountName when the incoming write doesn't carry them (e.g.\n\t\t// the model re-stores the primary session with an empty account, after reconcile enriched it).\n\t\tconst type = descriptor.type ?? existing?.type;\n\t\tconst accountName = descriptor.accountName ?? existing?.accountName;\n\t\t// A write without a workspace (a failed lookup, or a session re-store) keeps the stored pair whole.\n\t\tconst resource = descriptor.resourceId != null ? descriptor : existing;\n\t\tconst normalized: ConfiguredIntegrationDescriptor = {\n\t\t\t...descriptor,\n\t\t\tprimary: primary,\n\t\t\ttype: type,\n\t\t\taccountName: accountName,\n\t\t\tresourceName: resource?.resourceName,\n\t\t\tresourceId: resource?.resourceId,\n\t\t};\n\n\t\tlet changed: boolean;\n\t\tif (existing != null) {\n\t\t\t// `baseUrl` is compared alongside `domain`, not folded into it: `domain` is normalized to a bare\n\t\t\t// host, so a connection re-pointed to another context path on the SAME host is identical by domain\n\t\t\t// and would otherwise be treated as unchanged — leaving the stored descriptor, and every warm\n\t\t\t// integration listening for the change, on the old address.\n\t\t\tif (\n\t\t\t\texisting.domain === normalized.domain &&\n\t\t\t\tsameConfiguredBaseUrl(existing.baseUrl, normalized.baseUrl) &&\n\t\t\t\texisting.expiresAt === normalized.expiresAt &&\n\t\t\t\texisting.scopes === normalized.scopes &&\n\t\t\t\t(existing.primary ?? false) === (normalized.primary ?? false) &&\n\t\t\t\texisting.type === normalized.type &&\n\t\t\t\texisting.accountName === normalized.accountName &&\n\t\t\t\texisting.resourceName === normalized.resourceName &&\n\t\t\t\texisting.resourceId === normalized.resourceId\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Only fire the change event on address/scopes/primary/type/accountName changes (ignore expiresAt churn)\n\t\t\tchanged =\n\t\t\t\texisting.domain !== normalized.domain ||\n\t\t\t\t!sameConfiguredBaseUrl(existing.baseUrl, normalized.baseUrl) ||\n\t\t\t\texisting.scopes !== normalized.scopes ||\n\t\t\t\t(existing.primary ?? false) !== (normalized.primary ?? false) ||\n\t\t\t\texisting.type !== normalized.type ||\n\t\t\t\texisting.accountName !== normalized.accountName ||\n\t\t\t\texisting.resourceName !== normalized.resourceName ||\n\t\t\t\texisting.resourceId !== normalized.resourceId;\n\n\t\t\t// remove the existing descriptor from the array\n\t\t\tdescriptors.splice(descriptors.indexOf(existing), 1);\n\t\t} else {\n\t\t\tchanged = true;\n\t\t}\n\n\t\tdescriptors.push(normalized);\n\t\tthis.configured.set(descriptor.integrationId, descriptors);\n\n\t\tif (changed) {\n\t\t\tthis.fireChange(descriptor.integrationId);\n\t\t}\n\t\tawait this.storeConfigured();\n\t}\n\n\tprivate async removeConfigured(\n\t\tid: IntegrationIds,\n\t\toptions: { connectionId: string; cloud: boolean | undefined },\n\t): Promise<void> {\n\t\tconst existing = this.configured.get(id);\n\t\tif (existing == null || existing.length === 0) return;\n\n\t\tconst removedPrimaryDomains = new Set<string | undefined>();\n\t\tconst descriptors: ConfiguredIntegrationDescriptor[] = [];\n\t\tfor (const d of existing) {\n\t\t\tif (\n\t\t\t\td.id === options.connectionId &&\n\t\t\t\t(options?.cloud == null ||\n\t\t\t\t\t(options?.cloud === true && d.cloud === true) ||\n\t\t\t\t\t(options?.cloud === false && d.cloud === false))\n\t\t\t) {\n\t\t\t\tif (d.primary) {\n\t\t\t\t\tremovedPrimaryDomains.add(d.domain);\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tdescriptors.push(d);\n\t\t}\n\n\t\tif (descriptors.length === existing.length) return; // nothing matched\n\n\t\t// Promote a secondary to primary when the removed connection was the primary and others remain\n\t\t// in the same primary scope, so the provider/host stays in a well-defined connected state.\n\t\tfor (const domain of removedPrimaryDomains) {\n\t\t\tif (descriptors.some(d => this.isInPrimaryScope(id, d, domain) && d.primary)) continue;\n\n\t\t\tconst index = descriptors.findIndex(d => this.isInPrimaryScope(id, d, domain));\n\t\t\tif (index !== -1) {\n\t\t\t\tdescriptors[index] = { ...descriptors[index], primary: true };\n\t\t\t}\n\t\t}\n\n\t\tthis.configured.set(id, descriptors);\n\t\tthis.fireChange(undefined, id);\n\t\tawait this.storeConfigured();\n\t}\n\n\tprivate withLock<T>(id: IntegrationIds, fn: () => Promise<T>): Promise<T> {\n\t\tconst run = (this._locks.get(id) ?? Promise.resolve()).then(fn);\n\t\tconst settled = run.then(\n\t\t\t() => undefined,\n\t\t\t() => undefined,\n\t\t);\n\t\tthis._locks.set(id, settled);\n\t\tvoid settled.then(() => {\n\t\t\tif (this._locks.get(id) === settled) {\n\t\t\t\tthis._locks.delete(id);\n\t\t\t}\n\t\t});\n\t\treturn run;\n\t}\n\n\t/**\n\t * Taken before a token is read or fetched, and handed to {@link storeSession}: a sign-out that lands after it\n\t * (a disconnect, a reauthentication, the connection being removed) refuses the store, so a token fetched across\n\t * it is not written back and reconnected on the next resolution (gitkraken/kepler#3546).\n\t */\n\tgetSignOutMark(): number {\n\t\treturn this._signOutEpoch;\n\t}\n\n\tprivate markSignOut(scope: string): void {\n\t\tthis._signOuts.set(scope, ++this._signOutEpoch);\n\t}\n\n\tprivate getHostScope(id: IntegrationIds, domain: string): string {\n\t\treturn `${id}|host:${hostFromDomain(domain) ?? domain}`;\n\t}\n\n\tprivate isSignedOutSince(id: IntegrationIds, session: ProviderAuthenticationSession, mark: number): boolean {\n\t\tconst since = (scope: string) => (this._signOuts.get(scope) ?? 0) > mark;\n\t\tif (since(id)) return true;\n\t\tif (isSelfManagedHostIntegrationId(id) && session.domain && since(this.getHostScope(id, session.domain))) {\n\t\t\treturn true;\n\t\t}\n\t\treturn since(`${id}|connection:${session.id}`);\n\t}\n\n\t/**\n\t * Stores the session's secret and descriptor together. With a `signOutMark`, nothing is stored, and `false` is\n\t * returned, when a sign-out covering the session landed after the mark was taken.\n\t */\n\tstoreSession(\n\t\tid: IntegrationIds,\n\t\tsession: ProviderAuthenticationSession,\n\t\toptions?: { signOutMark?: number; resource?: ConnectionResource },\n\t): Promise<boolean> {\n\t\treturn this.withLock(id, async () => {\n\t\t\tif (options?.signOutMark != null && this.isSignedOutSince(id, session, options.signOutMark)) return false;\n\n\t\t\tconst previous = await this.readSecret(id, session.id, session.cloud);\n\t\t\tif (getSessionIdentity(previous) !== getSessionIdentity(session)) {\n\t\t\t\t// Readers share this lock, so none can resolve the retired token after this synchronous fence.\n\t\t\t\tthis._onWillChangeSession.fire({\n\t\t\t\t\tintegrationId: id,\n\t\t\t\t\tsession: session,\n\t\t\t\t\tpreviousDomain: previous?.domain,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tawait this.writeSecret(id, session, options?.resource);\n\t\t\treturn true;\n\t\t});\n\t}\n\n\tgetStoredSession(\n\t\tid: IntegrationIds,\n\t\tdescriptor: IntegrationAuthenticationSessionDescriptor,\n\t): Promise<ProviderAuthenticationSession | undefined> {\n\t\t// Under the lock too: reading can repair storage (a legacy local-key cloud session, a missing descriptor).\n\t\treturn this.withLock(id, async () => {\n\t\t\tconst sessionId = this.resolveConnectionId(id, descriptor);\n\t\t\tlet session = descriptor.cloud === true ? undefined : await this.readSecret(id, sessionId, false);\n\n\t\t\tlet cloudIfMissing = false;\n\t\t\tif (session != null) {\n\t\t\t\t// Check the `expiresAt` field\n\t\t\t\t// If it has an expiresAt property and the key is the old type, then it's a cloud session,\n\t\t\t\t// so delete it from the local key and\n\t\t\t\t// store with the \"cloud\" type key, and then use that one.\n\t\t\t\t// Otherwise it's a local session under the local key, so just return it.\n\t\t\t\tif (session.expiresAt != null) {\n\t\t\t\t\tcloudIfMissing = true;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait this.deleteSecrets(id, session.id);\n\t\t\t\t\t\tawait this.writeSecret(id, session);\n\t\t\t\t\t} catch {}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If no local session we try to restore a session with the cloud key\n\t\t\tif (session == null && descriptor.cloud !== false) {\n\t\t\t\tcloudIfMissing = true;\n\t\t\t\tsession = await this.readSecret(id, sessionId, true);\n\t\t\t}\n\n\t\t\treturn convertStoredSessionToSession(session, descriptor, cloudIfMissing);\n\t\t});\n\t}\n\n\t/**\n\t * Deletes one connection's stored session. `signOut` is for a delete that signs the integration out (a forced new\n\t * session): it also refuses the store of any token of the provider, or of the descriptor's self-managed host,\n\t * fetched before it (see {@link getSignOutMark}). A cleanup of a replaced token leaves it unset.\n\t */\n\tdeleteStoredSessions(\n\t\tid: IntegrationIds,\n\t\tdescriptor: IntegrationAuthenticationSessionDescriptor,\n\t\tcloud?: boolean,\n\t\toptions?: { preserveConfigured?: boolean; signOut?: boolean },\n\t): Promise<void> {\n\t\treturn this.withLock(id, async () => {\n\t\t\tif (options?.signOut) {\n\t\t\t\tthis.markSignOut(\n\t\t\t\t\tisSelfManagedHostIntegrationId(id) && descriptor.domain\n\t\t\t\t\t\t? this.getHostScope(id, descriptor.domain)\n\t\t\t\t\t\t: id,\n\t\t\t\t);\n\t\t\t}\n\t\t\tawait this.deleteSecrets(id, this.resolveConnectionId(id, descriptor), cloud, options);\n\t\t});\n\t}\n\n\t/** Signs out of every stored session of the provider, or of one self-managed host when `domain` is given. */\n\tdeleteAllStoredSessions(id: IntegrationIds, cloud?: boolean, domain?: string): Promise<void> {\n\t\treturn this.withLock(id, async () => {\n\t\t\tthis.markSignOut(isSelfManagedHostIntegrationId(id) && domain != null ? this.getHostScope(id, domain) : id);\n\t\t\tawait this.deleteAllSecrets(id, cloud, domain);\n\t\t});\n\t}\n\n\t/**\n\t * Reclaims all stored configuration + secrets for the given (typically retired) integration ids.\n\t * Used to clean up state left behind when an id is removed from the model — e.g. the local\n\t * self-managed `github-enterprise`/`gitlab-self-hosted` ids dropped when integrations went cloud-only.\n\t * Domains are read from the stored config (secrets are keyed by domain); ids with no stored config\n\t * are a no-op.\n\t */\n\tasync purgeStoredConfiguration(ids: readonly string[]): Promise<void> {\n\t\tconst stored =\n\t\t\tthis.ctx.storage.get<Record<string, StoredConfiguredIntegrationDescriptor[] | undefined>>(\n\t\t\t\t'integrations:configured',\n\t\t\t);\n\t\tif (stored == null) return;\n\n\t\tlet changed = false;\n\t\tfor (const id of ids) {\n\t\t\tif (!(id in stored)) continue;\n\n\t\t\tfor (const descriptor of stored[id] ?? []) {\n\t\t\t\t// Mirror the hydration backfill so the secret keys we delete match what was written: fall back\n\t\t\t\t// through domain, the provider's canonical domain, then the integration id (never empty). A\n\t\t\t\t// legacy cloud descriptor stored neither id nor domain, so an empty connection id here would\n\t\t\t\t// miss the canonical-domain secret (e.g. `integration.auth.cloud:github|github.com`) and orphan it.\n\t\t\t\tconst connectionId =\n\t\t\t\t\tdescriptor.id || descriptor.domain || providersMetadata[id as IntegrationIds]?.domain || id;\n\t\t\t\tawait this.ctx.storage.deleteSecret(this.getLocalSecretKey(id as IntegrationIds, connectionId));\n\t\t\t\tawait this.ctx.storage.deleteSecret(this.getCloudSecretKey(id as IntegrationIds, connectionId));\n\t\t\t\tif (descriptor.domain) {\n\t\t\t\t\tawait this.ctx.storage.deleteWorkspace(`connected:${id}:${descriptor.domain}`);\n\t\t\t\t}\n\t\t\t}\n\t\t\tchanged = true;\n\t\t}\n\t\tif (!changed) return;\n\n\t\tconst remaining = Object.fromEntries(Object.entries(stored).filter(([key]) => !ids.includes(key)));\n\t\tawait this.ctx.storage.store('integrations:configured', remaining as StoredIntegrationConfigurations);\n\t}\n\n\tprivate async deleteSecrets(\n\t\tid: IntegrationIds,\n\t\tconnectionId: string,\n\t\tcloud?: boolean,\n\t\toptions?: { preserveConfigured?: boolean },\n\t): Promise<void> {\n\t\tif (cloud == null || cloud === false) {\n\t\t\tawait this.ctx.storage.deleteSecret(this.getLocalSecretKey(id, connectionId));\n\t\t}\n\n\t\tif (cloud == null || cloud === true) {\n\t\t\tawait this.ctx.storage.deleteSecret(this.getCloudSecretKey(id, connectionId));\n\t\t}\n\n\t\tif (options?.preserveConfigured) return;\n\n\t\tawait this.removeConfigured(id, { connectionId: connectionId, cloud: cloud });\n\t}\n\n\tprivate async deleteAllSecrets(id: IntegrationIds, cloud?: boolean, domain?: string): Promise<void> {\n\t\t// Delete every connection's secret (multi-account): secrets are keyed per connection id, so a\n\t\t// single canonical-domain delete would orphan secondary tokens. When a domain is given (self-managed\n\t\t// disconnect of one host), scope to that host so other hosts under the same provider id survive.\n\t\tconst descriptors = this.configured.get(id);\n\t\tconst connectionIds = [\n\t\t\t...new Set(\n\t\t\t\t(domain != null ? descriptors?.filter(c => this.domainsMatch(id, c.domain, domain)) : descriptors)?.map(\n\t\t\t\t\tc => c.id,\n\t\t\t\t) ?? [],\n\t\t\t),\n\t\t];\n\t\tif (connectionIds.length) {\n\t\t\tfor (const connectionId of connectionIds) {\n\t\t\t\tawait this.deleteSecrets(id, connectionId, cloud);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\t// A domain-scoped clear that matched nothing means this host has no stored connections, so it must be\n\t\t// a no-op. The canonical-domain fallback below would target a bogus key (self-managed canonical domain\n\t\t// is empty), so skip it.\n\t\tif (domain != null) return;\n\n\t\t// No configured connections (e.g. an orphaned secret with no descriptor): fall back to the\n\t\t// provider's canonical domain, which is the legacy session id for cloud providers. Mirror the\n\t\t// hydration backfill's `|| id` guard so a self-managed provider (empty canonical domain) doesn't\n\t\t// target an ambiguous empty connection id.\n\t\tawait this.deleteSecrets(id, providersMetadata[id]?.domain || id, cloud);\n\t}\n\n\tprivate async writeSecret(\n\t\tid: IntegrationIds,\n\t\tsession: ProviderAuthenticationSession | StoredSession,\n\t\tresource?: ConnectionResource,\n\t): Promise<void> {\n\t\tawait this.ctx.storage.storeSecret(\n\t\t\tthis.getSecretKey(id, session.id, session.cloud ?? false),\n\t\t\tJSON.stringify(session),\n\t\t);\n\n\t\tawait this.addOrUpdateConfigured({\n\t\t\tid: session.id,\n\t\t\tintegrationId: id,\n\t\t\tdomain: isSelfManagedHostIntegrationId(id) ? session.domain : undefined,\n\t\t\tbaseUrl: isSelfManagedHostIntegrationId(id) ? session.baseUrl : undefined,\n\t\t\texpiresAt: session.expiresAt,\n\t\t\tscopes: session.scopes.join(','),\n\t\t\tcloud: session.cloud ?? false,\n\t\t\ttype: session.type,\n\t\t\taccountName: session.account?.label || undefined,\n\t\t\tresourceName: resource?.name,\n\t\t\tresourceId: resource?.id,\n\t\t});\n\t}\n\n\tprivate async readSecret(\n\t\tid: IntegrationIds,\n\t\tsessionId: string,\n\t\tcloud: boolean = false,\n\t): Promise<StoredSession | undefined> {\n\t\tlet storedSession: StoredSession | undefined;\n\t\ttry {\n\t\t\tconst sessionJSON = await this.ctx.storage.getSecret(this.getSecretKey(id, sessionId, cloud));\n\t\t\tif (sessionJSON) {\n\t\t\t\tstoredSession = JSON.parse(sessionJSON);\n\t\t\t\tif (storedSession != null) {\n\t\t\t\t\tconst configured = this.configured.get(id);\n\t\t\t\t\tconst connectionId = storedSession.id ?? sessionId;\n\t\t\t\t\tconst sessionCloud = storedSession.cloud ?? cloud;\n\t\t\t\t\tconst domain = isSelfManagedHostIntegrationId(id)\n\t\t\t\t\t\t? (storedSession.domain ?? storedSession.id)\n\t\t\t\t\t\t: undefined;\n\t\t\t\t\tif (\n\t\t\t\t\t\tconfigured == null ||\n\t\t\t\t\t\tconfigured.length === 0 ||\n\t\t\t\t\t\t!configured.some(\n\t\t\t\t\t\t\tc => c.id === connectionId && c.integrationId === id && c.cloud === sessionCloud,\n\t\t\t\t\t\t)\n\t\t\t\t\t) {\n\t\t\t\t\t\tawait this.addOrUpdateConfigured({\n\t\t\t\t\t\t\tid: connectionId,\n\t\t\t\t\t\t\tintegrationId: id,\n\t\t\t\t\t\t\tdomain: domain,\n\t\t\t\t\t\t\t// Rebuilt from the secret, so it must carry the address the session does; omitting it\n\t\t\t\t\t\t\t// leaves the descriptor claiming no context path and makes reconcile read every\n\t\t\t\t\t\t\t// routine check-in as a re-pointed connection.\n\t\t\t\t\t\t\tbaseUrl: isSelfManagedHostIntegrationId(id) ? storedSession.baseUrl : undefined,\n\t\t\t\t\t\t\texpiresAt: storedSession.expiresAt,\n\t\t\t\t\t\t\tscopes: storedSession.scopes.join(','),\n\t\t\t\t\t\t\tcloud: sessionCloud,\n\t\t\t\t\t\t\ttype: storedSession.type,\n\t\t\t\t\t\t\taccountName: storedSession.account?.label || undefined,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (_ex) {\n\t\t\ttry {\n\t\t\t\tawait this.deleteSecrets(id, sessionId, cloud);\n\t\t\t} catch {}\n\t\t}\n\t\treturn storedSession;\n\t}\n\n\tprivate getSecretKey(\n\t\tid: IntegrationIds,\n\t\tsessionId: string,\n\t\tcloud: boolean = false,\n\t): `integration.auth:${IntegrationIds}|${string}` | `integration.auth.cloud:${IntegrationIds}|${string}` {\n\t\treturn cloud ? this.getCloudSecretKey(id, sessionId) : this.getLocalSecretKey(id, sessionId);\n\t}\n\n\tprivate getLocalSecretKey(id: IntegrationIds, sessionId: string): `integration.auth:${IntegrationIds}|${string}` {\n\t\treturn `integration.auth:${id}|${sessionId}`;\n\t}\n\n\tprivate getCloudSecretKey(\n\t\tid: IntegrationIds,\n\t\tsessionId: string,\n\t): `integration.auth.cloud:${IntegrationIds}|${string}` {\n\t\treturn `integration.auth.cloud:${id}|${sessionId}`;\n\t}\n\n\tprivate getPrimaryScope(\n\t\tid: IntegrationIds,\n\t\tdescriptors: ConfiguredIntegrationDescriptor[],\n\t\tdomain: string | undefined,\n\t): ConfiguredIntegrationDescriptor[] {\n\t\treturn isSelfManagedHostIntegrationId(id)\n\t\t\t? descriptors.filter(d => this.isInPrimaryScope(id, d, domain))\n\t\t\t: descriptors;\n\t}\n\n\tprivate isInPrimaryScope(\n\t\tid: IntegrationIds,\n\t\tdescriptor: ConfiguredIntegrationDescriptor,\n\t\tdomain: string | undefined,\n\t): boolean {\n\t\treturn !isSelfManagedHostIntegrationId(id) || this.domainsMatch(id, descriptor.domain, domain);\n\t}\n\n\t/**\n\t * Resolves the connection id used as the secret-key session id for an auth descriptor.\n\t * - If the descriptor targets a specific connection (`connectionId`), that wins.\n\t * - Otherwise returns the primary connection's id for the provider (matching the descriptor's domain\n\t * for self-managed hosts; any connection for cloud hosts, where the stored domain is undefined).\n\t * - Falls back to the descriptor domain when nothing is configured yet, preserving legacy\n\t * (pre-multi-account) reads with zero secret migration.\n\t */\n\tresolveConnectionId(id: IntegrationIds, descriptor: IntegrationAuthenticationSessionDescriptor): string {\n\t\t// An empty connectionId is not a real target — treat it as \"no target\" so it resolves the primary\n\t\t// rather than keying a secret under an empty id.\n\t\tif (descriptor.connectionId) return descriptor.connectionId;\n\n\t\tconst domain = isSelfManagedHostIntegrationId(id) ? descriptor.domain : undefined;\n\t\tconst candidates = this.scopeConnectionCandidates(id, domain, descriptor.cloud);\n\t\treturn (candidates?.find(c => c.primary) ?? candidates?.[0])?.id ?? descriptor.domain;\n\t}\n\n\t/**\n\t * Returns the id of the configured connection an unscoped descriptor resolves to (the primary for the\n\t * descriptor's domain, matching {@link resolveConnectionId}'s selection), or `undefined` when nothing is\n\t * configured for it. Unlike {@link resolveConnectionId} this only returns a genuine per-connection cloud\n\t * token id (never a local/PAT or domain-derived legacy id), so callers can safely use it to scope a cloud\n\t * token fetch to one host of a multi-host self-managed provider, or fall through to the provider-global\n\t * primary endpoint on `undefined`.\n\t */\n\t/**\n\t * The address already stored for a self-managed connection — see {@link ConfiguredIntegrationDescriptor.baseUrl}.\n\t *\n\t * Exists so a session rebuilt from a backend response that omits the domain can keep the address the\n\t * connection was configured with, rather than silently falling back to the bare host and losing a context\n\t * path the user never changed. Looked up by connection id first, then by host for an unscoped fetch.\n\t */\n\t/**\n\t * Whether `connectionId` names a cloud connection configured for `domain`'s host.\n\t *\n\t * The caller-facing question is \"is this id evidence that a token belongs to this host\". A connection id\n\t * can arrive from a caller rather than from our own configuration, so it is only evidence once it matches\n\t * a descriptor we stored for that host — see the host guard in `CloudIntegrationAuthenticationProvider`.\n\t */\n\tisConnectionConfiguredForHost(\n\t\tid: IntegrationIds,\n\t\tconnectionId: string | undefined,\n\t\tdomain: string | undefined,\n\t): boolean {\n\t\tif (connectionId == null) return false;\n\n\t\tconst connection = this.getConfigured(id, { cloud: true }).find(c => c.id === connectionId);\n\t\tif (connection == null) return false;\n\n\t\treturn !isSelfManagedHostIntegrationId(id) || this.domainsMatch(id, connection.domain, domain);\n\t}\n\n\tgetConfiguredBaseUrl(id: IntegrationIds, connectionId: string | undefined, domain?: string): string | undefined {\n\t\tif (!isSelfManagedHostIntegrationId(id)) return undefined;\n\n\t\tconst configured = this.getConfigured(id, { cloud: true });\n\t\tconst byId = connectionId != null ? configured.find(c => c.id === connectionId) : undefined;\n\t\tif (byId != null) return byId.baseUrl;\n\n\t\treturn configured.find(c => this.domainsMatch(id, c.domain, domain))?.baseUrl;\n\t}\n\n\tgetConfiguredConnectionId(id: IntegrationIds, domain: string | undefined, cloud?: boolean): string | undefined {\n\t\tconst scoped = isSelfManagedHostIntegrationId(id) ? domain : undefined;\n\t\tconst candidates = this.scopeConnectionCandidates(id, scoped, cloud);\n\t\tconst connection = candidates?.find(c => c.primary) ?? candidates?.[0];\n\t\tif (connection == null) return undefined;\n\n\t\t// Only return a real per-connection cloud token id. Reject a local (PAT) descriptor (surfaced by\n\t\t// scopeConnectionCandidates' non-cloud fallback) and a domain-derived legacy id (the descriptor's own\n\t\t// domain or the provider's canonical domain — see ConfiguredIntegrationDescriptor.id), either of which\n\t\t// would target `v1/provider-tokens/tokens/{domain}` (rejected as a non-uuid). Callers then fall through\n\t\t// to the provider-scoped primary endpoint.\n\t\tif (!connection.cloud) return undefined;\n\n\t\tconst canonicalDomain = providersMetadata[id]?.domain;\n\t\tif (connection.id === connection.domain || (canonicalDomain && connection.id === canonicalDomain)) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn connection.id;\n\t}\n\n\t/**\n\t * Selects configured descriptors for a provider matching `domain`, further narrowed to the `cloud`\n\t * variant when specified. A connection id can have both a local (PAT) and cloud descriptor whose ids\n\t * differ (e.g. a legacy local descriptor keyed by domain alongside a real cloud token id); scoping by\n\t * `cloud` keeps a cloud-scoped read/delete from resolving the local id (and vice versa). Falls back to\n\t * the domain-only set when no variant matches, so legacy single-variant resolution is unchanged.\n\t */\n\tprivate scopeConnectionCandidates(\n\t\tid: IntegrationIds,\n\t\tdomain: string | undefined,\n\t\tcloud: boolean | undefined,\n\t): ConfiguredIntegrationDescriptor[] | undefined {\n\t\tconst candidates = this.configured.get(id)?.filter(c => this.domainsMatch(id, c.domain, domain));\n\t\tif (cloud == null || candidates == null) return candidates;\n\n\t\tconst scoped = candidates.filter(c => c.cloud === cloud);\n\t\treturn scoped.length ? scoped : candidates;\n\t}\n\n\t/**\n\t * Marks the given connection as the primary/default for the provider and clears the flag on its\n\t * siblings. Persists immediately instead of relying on a session re-store to carry the primary flag.\n\t */\n\tsetPrimaryConnection(id: IntegrationIds, connectionId: string): Promise<void> {\n\t\treturn this.withLock(id, () => this.setPrimaryConnectionCore(id, connectionId));\n\t}\n\n\tprivate async setPrimaryConnectionCore(id: IntegrationIds, connectionId: string): Promise<void> {\n\t\tconst descriptors = this.configured.get(id);\n\t\tif (descriptors == null || descriptors.length === 0) return;\n\t\tif (!descriptors.some(d => d.id === connectionId)) return;\n\n\t\tconst target =\n\t\t\tdescriptors.find(d => d.id === connectionId && d.cloud) ?? descriptors.find(d => d.id === connectionId);\n\t\tif (target == null) return;\n\n\t\tconst domain = isSelfManagedHostIntegrationId(id) ? target.domain : undefined;\n\t\t// A connection id can have both a local (PAT) and cloud descriptor. Mark the primary on a single\n\t\t// canonical variant (prefer cloud, since multi-account primaries are cloud-driven) within the\n\t\t// provider/host scope, so other self-managed hosts keep their own default connection.\n\t\tconst primaryIsCloud = descriptors.some(\n\t\t\td => d.id === connectionId && d.cloud && this.isInPrimaryScope(id, d, domain),\n\t\t);\n\n\t\tlet changed = false;\n\t\tconst updated = descriptors.map(d => {\n\t\t\tif (!this.isInPrimaryScope(id, d, domain)) return d;\n\n\t\t\tconst primary = d.id === connectionId && (d.cloud ?? false) === primaryIsCloud;\n\t\t\tif ((d.primary ?? false) === primary) return d;\n\n\t\t\tchanged = true;\n\t\t\treturn { ...d, primary: primary };\n\t\t});\n\t\tif (!changed) return;\n\n\t\tthis.configured.set(id, updated);\n\t\tthis.fireChange(id);\n\t\tawait this.storeConfigured();\n\t}\n\n\t/**\n\t * Removes a single connection (its secret + configured descriptor). If it was the primary and other\n\t * connections remain, a secondary is promoted (see {@link removeConfigured}). Unlike\n\t * {@link deleteAllStoredSessions}, this only affects the targeted connection. Pass `cloud` to scope\n\t * the removal to the cloud/local variant when a local PAT and a cloud session share a connection id.\n\t */\n\tdeleteConnection(id: IntegrationIds, connectionId: string, cloud?: boolean): Promise<void> {\n\t\treturn this.withLock(id, async () => {\n\t\t\t// The connection is gone, so a token of it fetched before must not be stored back.\n\t\t\tthis.markSignOut(`${id}|connection:${connectionId}`);\n\t\t\tawait this.deleteSecrets(id, connectionId, cloud);\n\t\t});\n\t}\n\n\tprivate _addedIds = new Set<IntegrationIds>();\n\tprivate _removedIds = new Set<IntegrationIds>();\n\tprivate _fireChangeDebounced?: () => void;\n\n\tprivate normalizeConfiguredDomain(id: IntegrationIds, domain: string | undefined): string | undefined {\n\t\tif (!isSelfManagedHostIntegrationId(id)) return domain;\n\n\t\treturn hostFromDomain(domain) ?? domain;\n\t}\n\n\tprivate domainsMatch(id: IntegrationIds, first: string | undefined, second: string | undefined): boolean {\n\t\tif (first === second) return true;\n\t\tif (!isSelfManagedHostIntegrationId(id)) return false;\n\t\tif (first == null || second == null) return false;\n\n\t\treturn areDomainsOnSameHost(first, second);\n\t}\n\n\tprivate fireChange(added?: IntegrationIds, removed?: IntegrationIds) {\n\t\tthis._fireChangeDebounced ??= debounce(() => {\n\t\t\tconst added = [...this._addedIds];\n\t\t\tthis._addedIds.clear();\n\t\t\tconst removed = [...this._removedIds];\n\t\t\tthis._removedIds.clear();\n\n\t\t\tthis._onDidChange.fire({ added: added, removed: removed });\n\t\t}, 250);\n\n\t\tif (added != null) {\n\t\t\tthis._addedIds.add(added);\n\t\t}\n\t\tif (removed != null) {\n\t\t\tthis._removedIds.add(removed);\n\t\t}\n\t\tthis._fireChangeDebounced();\n\t}\n}\n\nfunction convertStoredSessionToSession(\n\tstoredSession: StoredSession | undefined,\n\tdescriptor: IntegrationAuthenticationSessionDescriptor,\n\tcloudIfMissing: boolean,\n): ProviderAuthenticationSession | undefined {\n\tif (storedSession == null) return undefined;\n\n\treturn {\n\t\tid: storedSession.id,\n\t\taccessToken: storedSession.accessToken,\n\t\taccount: {\n\t\t\tid: storedSession.account?.id ?? '',\n\t\t\tlabel: storedSession.account?.label ?? '',\n\t\t},\n\t\tscopes: storedSession.scopes,\n\t\tcloud: storedSession.cloud ?? cloudIfMissing,\n\t\texpiresAt: storedSession.expiresAt ? new Date(storedSession.expiresAt) : undefined,\n\t\tdomain: storedSession.domain ?? descriptor.domain,\n\t\tbaseUrl: getStoredBaseUrl(storedSession.baseUrl, storedSession.domain, storedSession.protocol),\n\t\tprotocol: storedSession.protocol,\n\t\ttype: storedSession.type,\n\t\t// Carried for providers whose client needs an app key alongside the token (e.g. Trello); without\n\t\t// this a rehydrated session silently loses the key and every read no-ops.\n\t\tappKey: storedSession.appKey,\n\t};\n}\n\nfunction getStoredBaseUrl(\n\tbaseUrl: string | undefined,\n\tdomain: string | undefined,\n\tprotocol?: string,\n): string | undefined {\n\tif (baseUrl != null) return baseUrl;\n\n\tconst legacyUrl = baseUrlFromDomain(domain, protocol);\n\treturn legacyUrl != null && new URL(legacyUrl).pathname !== '/' ? legacyUrl : undefined;\n}\n"],"mappings":"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"}
@@ -2,8 +2,9 @@ import { debug } from "../../../utils/decorators/log.js";
2
2
  import __decorate from "../../../_virtual/@oxc-project+runtime/helpers/esm/decorate.js";
3
3
  import { gate } from "../../../utils/decorators/gate.js";
4
4
  import "../constants.js";
5
- import { supportedIntegrationIds } from "../utils/integration.utils.js";
5
+ import { isSelfManagedHostIntegrationId, supportedIntegrationIds } from "../utils/integration.utils.js";
6
6
  import { CloudIntegrationAuthenticationProvider } from "./integrationAuthenticationProvider.js";
7
+ import { ObservedAuthenticationProvider } from "./observedAuthenticationProvider.js";
7
8
  //#region ../plus/integrations/src/authentication/integrationAuthenticationService.ts
8
9
  var IntegrationAuthenticationService = class {
9
10
  configuredIntegrationService;
@@ -70,8 +71,9 @@ var IntegrationAuthenticationService = class {
70
71
  if (provider != null) return provider;
71
72
  const hostProvider = await this.ctx.hooks?.createAuthenticationProvider?.({ id: providerId });
72
73
  if (hostProvider != null) {
73
- this.providers.set(providerId, hostProvider);
74
- return hostProvider;
74
+ provider = new ObservedAuthenticationProvider(hostProvider, isSelfManagedHostIntegrationId(providerId), (publication, domains) => this.getIntegrationService().onSessionPublishing(providerId, publication, domains));
75
+ this.providers.set(providerId, provider);
76
+ return provider;
75
77
  }
76
78
  switch (providerId) {
77
79
  case "github":
@@ -1 +1 @@
1
- {"version":3,"file":"integrationAuthenticationService.js","names":[],"sources":["../../../../../plus/integrations/src/authentication/integrationAuthenticationService.ts"],"sourcesContent":["import type { GitRemote } from '@gitlens/git/models/remote.js';\nimport { gate } from '@gitlens/utils/decorators/gate.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport type { Disposable } from '@gitlens/utils/disposable.js';\nimport type { IntegrationIds, SupportedCloudIntegrationIds } from '../constants.js';\nimport {\n\tGitCloudHostIntegrationId,\n\tGitSelfManagedHostIntegrationId,\n\tIssuesCloudHostIntegrationId,\n\tIssuesSelfManagedHostIntegrationId,\n} from '../constants.js';\nimport type { IntegrationServiceContext } from '../context.js';\nimport type { IntegrationService } from '../integrationService.js';\nimport type { GitHostIntegration } from '../models/gitHostIntegration.js';\nimport type { ApiClients } from '../providers/apiClients.js';\nimport type { Source } from '../telemetry.js';\nimport { supportedIntegrationIds } from '../utils/integration.utils.js';\nimport type { CloudIntegrationService } from './cloudIntegrationService.js';\nimport type { ConfiguredIntegrationService } from './configuredIntegrationService.js';\nimport type { IntegrationAuthenticationProvider } from './integrationAuthenticationProvider.js';\nimport { CloudIntegrationAuthenticationProvider } from './integrationAuthenticationProvider.js';\n\nexport class IntegrationAuthenticationService implements Disposable {\n\tprivate readonly providers = new Map<IntegrationIds, IntegrationAuthenticationProvider>();\n\n\tconstructor(\n\t\tprivate readonly configuredIntegrationService: ConfiguredIntegrationService,\n\t\treadonly ctx: IntegrationServiceContext,\n\t\t/**\n\t\t * Lazy accessor for the owning {@link IntegrationService}. Injected by the composition root\n\t\t * ({@link createIntegrationManager}) to break the auth↔service construction cycle without a\n\t\t * mutable setter or a host round-trip; only resolved at runtime (long after construction).\n\t\t */\n\t\tprivate readonly getIntegrationService: () => IntegrationService,\n\t\t/** The package's cloud token-exchange client, constructed by the composition root. */\n\t\treadonly cloudIntegrations: CloudIntegrationService,\n\t) {}\n\n\tdispose(): void {\n\t\tthis.providers.forEach(p => p.dispose());\n\t\tthis.providers.clear();\n\t}\n\n\t/**\n\t * Initiates the cloud-integration connect flow on the owning service. Cloud auth providers call\n\t * this when they need a session that doesn't exist yet (see\n\t * {@link CloudIntegrationAuthenticationProvider}).\n\t */\n\tconnectCloudIntegrations(\n\t\tconnect: { integrationIds: SupportedCloudIntegrationIds[]; skipIfConnected?: boolean; skipPreSync?: boolean },\n\t\tsource?: Source,\n\t): Promise<boolean> {\n\t\treturn this.getIntegrationService().connectCloudIntegrations(connect, source);\n\t}\n\n\t/**\n\t * Resolves the connected git-host integration for a `GitRemote`, via the owning service. Lets\n\t * package-internal callers (e.g. the Bitbucket provider) resolve a remote's integration without a\n\t * host round-trip.\n\t */\n\tgetByRemote(remote: GitRemote): Promise<GitHostIntegration | undefined> {\n\t\treturn this.getIntegrationService().getByRemote(remote);\n\t}\n\n\t/** Resolves the per-integration `ignoreSSLErrors` flag via the owning service (host-config-backed). */\n\tignoreSSLErrors(integration: GitHostIntegration | { id: IntegrationIds; domain?: string }): boolean | 'force' {\n\t\treturn this.getIntegrationService().ignoreSSLErrors(integration);\n\t}\n\n\t/** The package-built per-provider API clients, via the owning service (built once + memoized there). */\n\tget apis(): ApiClients {\n\t\treturn this.getIntegrationService().apis;\n\t}\n\n\tasync get(providerId: IntegrationIds): Promise<IntegrationAuthenticationProvider> {\n\t\treturn this.ensureProvider(providerId);\n\t}\n\n\t@debug()\n\tasync reset(): Promise<void> {\n\t\t// TODO: This really isn't ideal, since it will only work for \"cloud\" providers as we won't have any more specific descriptors\n\t\tawait Promise.allSettled(\n\t\t\tsupportedIntegrationIds.map(async providerId =>\n\t\t\t\t(await this.ensureProvider(providerId)).deleteAllSessions(),\n\t\t\t),\n\t\t);\n\t}\n\n\tsupports(providerId: string): boolean {\n\t\t// Linear and Trello are cloud-backed issue integrations (same as Jira): `ensureProvider` registers a\n\t\t// cloud auth provider for them, so a disconnect must offer to sign out of the cloud token too —\n\t\t// otherwise the backend token and configured connection survive the disable.\n\t\tswitch (providerId) {\n\t\t\tcase GitCloudHostIntegrationId.AzureDevOps:\n\t\t\tcase GitSelfManagedHostIntegrationId.AzureDevOpsServer:\n\t\t\tcase GitCloudHostIntegrationId.Bitbucket:\n\t\t\tcase GitCloudHostIntegrationId.GitLab:\n\t\t\tcase IssuesCloudHostIntegrationId.Jira:\n\t\t\tcase IssuesSelfManagedHostIntegrationId.JiraServer:\n\t\t\tcase IssuesCloudHostIntegrationId.Linear:\n\t\t\tcase IssuesCloudHostIntegrationId.Trello:\n\t\t\tcase GitCloudHostIntegrationId.GitHub:\n\t\t\t\treturn true;\n\t\t\tdefault:\n\t\t\t\treturn false;\n\t\t}\n\t}\n\n\t@gate()\n\tprivate async ensureProvider(providerId: IntegrationIds): Promise<IntegrationAuthenticationProvider> {\n\t\tlet provider = this.providers.get(providerId);\n\t\tif (provider != null) return provider;\n\n\t\t// Optional consumer override for custom auth (e.g. a manual-token provider). GitLens omits it —\n\t\t// the package constructs its own cloud providers below (so GitLens's cloud auth needs no host hook).\n\t\tconst hostProvider = await this.ctx.hooks?.createAuthenticationProvider?.({\n\t\t\tid: providerId,\n\t\t});\n\t\tif (hostProvider != null) {\n\t\t\tthis.providers.set(providerId, hostProvider);\n\t\t\treturn hostProvider;\n\t\t}\n\n\t\t// Every cloud integration shares one provider, parameterized by id (cloud-only).\n\t\tswitch (providerId) {\n\t\t\tcase GitCloudHostIntegrationId.GitHub:\n\t\t\tcase GitSelfManagedHostIntegrationId.CloudGitHubEnterprise:\n\t\t\tcase GitCloudHostIntegrationId.GitLab:\n\t\t\tcase GitSelfManagedHostIntegrationId.CloudGitLabSelfHosted:\n\t\t\tcase GitCloudHostIntegrationId.AzureDevOps:\n\t\t\tcase GitSelfManagedHostIntegrationId.AzureDevOpsServer:\n\t\t\tcase GitCloudHostIntegrationId.Bitbucket:\n\t\t\tcase GitSelfManagedHostIntegrationId.BitbucketServer:\n\t\t\tcase IssuesCloudHostIntegrationId.Jira:\n\t\t\tcase IssuesSelfManagedHostIntegrationId.JiraServer:\n\t\t\tcase IssuesCloudHostIntegrationId.Linear:\n\t\t\tcase IssuesCloudHostIntegrationId.Trello:\n\t\t\t\tprovider = new CloudIntegrationAuthenticationProvider(\n\t\t\t\t\tthis,\n\t\t\t\t\tthis.configuredIntegrationService,\n\t\t\t\t\tproviderId,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`No authentication provider registered for integration '${String(providerId)}'`);\n\t\t}\n\n\t\tthis.providers.set(providerId, provider);\n\t\treturn provider;\n\t}\n}\n"],"mappings":";;;;;;;AAsBA,IAAa,mCAAb,MAAoE;CAIjD;CACR;CAMQ;CAER;CAZV,4BAA6B,IAAI,IAAuD;CAExF,YACC,8BACA,KAMA,uBAEA,mBACC;EAVgB,KAAA,+BAAA;EACR,KAAA,MAAA;EAMQ,KAAA,wBAAA;EAER,KAAA,oBAAA;CACP;CAEH,UAAgB;EACf,KAAK,UAAU,SAAQ,MAAK,EAAE,QAAQ,CAAC;EACvC,KAAK,UAAU,MAAM;CACtB;;;;;;CAOA,yBACC,SACA,QACmB;EACnB,OAAO,KAAK,sBAAsB,CAAC,CAAC,yBAAyB,SAAS,MAAM;CAC7E;;;;;;CAOA,YAAY,QAA4D;EACvE,OAAO,KAAK,sBAAsB,CAAC,CAAC,YAAY,MAAM;CACvD;;CAGA,gBAAgB,aAA8F;EAC7G,OAAO,KAAK,sBAAsB,CAAC,CAAC,gBAAgB,WAAW;CAChE;;CAGA,IAAI,OAAmB;EACtB,OAAO,KAAK,sBAAsB,CAAC,CAAC;CACrC;CAEA,MAAM,IAAI,YAAwE;EACjF,OAAO,KAAK,eAAe,UAAU;CACtC;CAEA,MACM,QAAuB;EAE5B,MAAM,QAAQ,WACb,wBAAwB,IAAI,OAAM,gBAChC,MAAM,KAAK,eAAe,UAAU,EAAA,CAAG,kBAAkB,CAC3D,CACD;CACD;CAEA,SAAS,YAA6B;EAIrC,QAAQ,YAAR;GACC,KAAA;GACA,KAAA;GACA,KAAA;GACA,KAAA;GACA,KAAA;GACA,KAAA;GACA,KAAA;GACA,KAAA;GACA,KAAA,UACC,OAAO;GACR,SACC,OAAO;EACT;CACD;CAEA,MACc,eAAe,YAAwE;EACpG,IAAI,WAAW,KAAK,UAAU,IAAI,UAAU;EAC5C,IAAI,YAAY,MAAM,OAAO;EAI7B,MAAM,eAAe,MAAM,KAAK,IAAI,OAAO,+BAA+B,EACzE,IAAI,WACL,CAAC;EACD,IAAI,gBAAgB,MAAM;GACzB,KAAK,UAAU,IAAI,YAAY,YAAY;GAC3C,OAAO;EACR;EAGA,QAAQ,YAAR;GACC,KAAA;GACA,KAAA;GACA,KAAA;GACA,KAAA;GACA,KAAA;GACA,KAAA;GACA,KAAA;GACA,KAAA;GACA,KAAA;GACA,KAAA;GACA,KAAA;GACA,KAAA;IACC,WAAW,IAAI,uCACd,MACA,KAAK,8BACL,UACD;IACA;GACD,SACC,MAAM,IAAI,MAAM,0DAA0D,OAAO,UAAU,EAAE,EAAE;EACjG;EAEA,KAAK,UAAU,IAAI,YAAY,QAAQ;EACvC,OAAO;CACR;AACD;AAxEE,WAAA,CAAA,MAAM,CAAA,GAAA,iCAAA,WAAA,SAAA,IAAA;AA8BN,WAAA,CAAA,KAAK,CAAA,GAAA,iCAAA,WAAA,kBAAA,IAAA"}
1
+ {"version":3,"file":"integrationAuthenticationService.js","names":[],"sources":["../../../../../plus/integrations/src/authentication/integrationAuthenticationService.ts"],"sourcesContent":["import type { GitRemote } from '@gitlens/git/models/remote.js';\nimport { gate } from '@gitlens/utils/decorators/gate.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport type { Disposable } from '@gitlens/utils/disposable.js';\nimport type { IntegrationIds, SupportedCloudIntegrationIds } from '../constants.js';\nimport {\n\tGitCloudHostIntegrationId,\n\tGitSelfManagedHostIntegrationId,\n\tIssuesCloudHostIntegrationId,\n\tIssuesSelfManagedHostIntegrationId,\n} from '../constants.js';\nimport type { IntegrationServiceContext } from '../context.js';\nimport type { IntegrationService } from '../integrationService.js';\nimport type { GitHostIntegration } from '../models/gitHostIntegration.js';\nimport type { ApiClients } from '../providers/apiClients.js';\nimport type { Source } from '../telemetry.js';\nimport { isSelfManagedHostIntegrationId, supportedIntegrationIds } from '../utils/integration.utils.js';\nimport type { CloudIntegrationService } from './cloudIntegrationService.js';\nimport type { ConfiguredIntegrationService } from './configuredIntegrationService.js';\nimport type { IntegrationAuthenticationProvider } from './integrationAuthenticationProvider.js';\nimport { CloudIntegrationAuthenticationProvider } from './integrationAuthenticationProvider.js';\nimport { ObservedAuthenticationProvider } from './observedAuthenticationProvider.js';\n\nexport class IntegrationAuthenticationService implements Disposable {\n\tprivate readonly providers = new Map<IntegrationIds, IntegrationAuthenticationProvider>();\n\n\tconstructor(\n\t\tprivate readonly configuredIntegrationService: ConfiguredIntegrationService,\n\t\treadonly ctx: IntegrationServiceContext,\n\t\t/**\n\t\t * Lazy accessor for the owning {@link IntegrationService}. Injected by the composition root\n\t\t * ({@link createIntegrationManager}) to break the auth↔service construction cycle without a\n\t\t * mutable setter or a host round-trip; only resolved at runtime (long after construction).\n\t\t */\n\t\tprivate readonly getIntegrationService: () => IntegrationService,\n\t\t/** The package's cloud token-exchange client, constructed by the composition root. */\n\t\treadonly cloudIntegrations: CloudIntegrationService,\n\t) {}\n\n\tdispose(): void {\n\t\tthis.providers.forEach(p => p.dispose());\n\t\tthis.providers.clear();\n\t}\n\n\t/**\n\t * Initiates the cloud-integration connect flow on the owning service. Cloud auth providers call\n\t * this when they need a session that doesn't exist yet (see\n\t * {@link CloudIntegrationAuthenticationProvider}).\n\t */\n\tconnectCloudIntegrations(\n\t\tconnect: { integrationIds: SupportedCloudIntegrationIds[]; skipIfConnected?: boolean; skipPreSync?: boolean },\n\t\tsource?: Source,\n\t): Promise<boolean> {\n\t\treturn this.getIntegrationService().connectCloudIntegrations(connect, source);\n\t}\n\n\t/**\n\t * Resolves the connected git-host integration for a `GitRemote`, via the owning service. Lets\n\t * package-internal callers (e.g. the Bitbucket provider) resolve a remote's integration without a\n\t * host round-trip.\n\t */\n\tgetByRemote(remote: GitRemote): Promise<GitHostIntegration | undefined> {\n\t\treturn this.getIntegrationService().getByRemote(remote);\n\t}\n\n\t/** Resolves the per-integration `ignoreSSLErrors` flag via the owning service (host-config-backed). */\n\tignoreSSLErrors(integration: GitHostIntegration | { id: IntegrationIds; domain?: string }): boolean | 'force' {\n\t\treturn this.getIntegrationService().ignoreSSLErrors(integration);\n\t}\n\n\t/** The package-built per-provider API clients, via the owning service (built once + memoized there). */\n\tget apis(): ApiClients {\n\t\treturn this.getIntegrationService().apis;\n\t}\n\n\tasync get(providerId: IntegrationIds): Promise<IntegrationAuthenticationProvider> {\n\t\treturn this.ensureProvider(providerId);\n\t}\n\n\t@debug()\n\tasync reset(): Promise<void> {\n\t\t// TODO: This really isn't ideal, since it will only work for \"cloud\" providers as we won't have any more specific descriptors\n\t\tawait Promise.allSettled(\n\t\t\tsupportedIntegrationIds.map(async providerId =>\n\t\t\t\t(await this.ensureProvider(providerId)).deleteAllSessions(),\n\t\t\t),\n\t\t);\n\t}\n\n\tsupports(providerId: string): boolean {\n\t\t// Linear and Trello are cloud-backed issue integrations (same as Jira): `ensureProvider` registers a\n\t\t// cloud auth provider for them, so a disconnect must offer to sign out of the cloud token too —\n\t\t// otherwise the backend token and configured connection survive the disable.\n\t\tswitch (providerId) {\n\t\t\tcase GitCloudHostIntegrationId.AzureDevOps:\n\t\t\tcase GitSelfManagedHostIntegrationId.AzureDevOpsServer:\n\t\t\tcase GitCloudHostIntegrationId.Bitbucket:\n\t\t\tcase GitCloudHostIntegrationId.GitLab:\n\t\t\tcase IssuesCloudHostIntegrationId.Jira:\n\t\t\tcase IssuesSelfManagedHostIntegrationId.JiraServer:\n\t\t\tcase IssuesCloudHostIntegrationId.Linear:\n\t\t\tcase IssuesCloudHostIntegrationId.Trello:\n\t\t\tcase GitCloudHostIntegrationId.GitHub:\n\t\t\t\treturn true;\n\t\t\tdefault:\n\t\t\t\treturn false;\n\t\t}\n\t}\n\n\t@gate()\n\tprivate async ensureProvider(providerId: IntegrationIds): Promise<IntegrationAuthenticationProvider> {\n\t\tlet provider = this.providers.get(providerId);\n\t\tif (provider != null) return provider;\n\n\t\t// Optional consumer override for custom auth (e.g. a manual-token provider). GitLens omits it —\n\t\t// the package constructs its own cloud providers below (so GitLens's cloud auth needs no host hook).\n\t\tconst hostProvider = await this.ctx.hooks?.createAuthenticationProvider?.({\n\t\t\tid: providerId,\n\t\t});\n\t\tif (hostProvider != null) {\n\t\t\tprovider = new ObservedAuthenticationProvider(\n\t\t\t\thostProvider,\n\t\t\t\tisSelfManagedHostIntegrationId(providerId),\n\t\t\t\t(publication, domains) =>\n\t\t\t\t\tthis.getIntegrationService().onSessionPublishing(providerId, publication, domains),\n\t\t\t);\n\t\t\tthis.providers.set(providerId, provider);\n\t\t\treturn provider;\n\t\t}\n\n\t\t// Every cloud integration shares one provider, parameterized by id (cloud-only).\n\t\tswitch (providerId) {\n\t\t\tcase GitCloudHostIntegrationId.GitHub:\n\t\t\tcase GitSelfManagedHostIntegrationId.CloudGitHubEnterprise:\n\t\t\tcase GitCloudHostIntegrationId.GitLab:\n\t\t\tcase GitSelfManagedHostIntegrationId.CloudGitLabSelfHosted:\n\t\t\tcase GitCloudHostIntegrationId.AzureDevOps:\n\t\t\tcase GitSelfManagedHostIntegrationId.AzureDevOpsServer:\n\t\t\tcase GitCloudHostIntegrationId.Bitbucket:\n\t\t\tcase GitSelfManagedHostIntegrationId.BitbucketServer:\n\t\t\tcase IssuesCloudHostIntegrationId.Jira:\n\t\t\tcase IssuesSelfManagedHostIntegrationId.JiraServer:\n\t\t\tcase IssuesCloudHostIntegrationId.Linear:\n\t\t\tcase IssuesCloudHostIntegrationId.Trello:\n\t\t\t\tprovider = new CloudIntegrationAuthenticationProvider(\n\t\t\t\t\tthis,\n\t\t\t\t\tthis.configuredIntegrationService,\n\t\t\t\t\tproviderId,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`No authentication provider registered for integration '${String(providerId)}'`);\n\t\t}\n\n\t\tthis.providers.set(providerId, provider);\n\t\treturn provider;\n\t}\n}\n"],"mappings":";;;;;;;;AAuBA,IAAa,mCAAb,MAAoE;CAIjD;CACR;CAMQ;CAER;CAZV,4BAA6B,IAAI,IAAuD;CAExF,YACC,8BACA,KAMA,uBAEA,mBACC;EAVgB,KAAA,+BAAA;EACR,KAAA,MAAA;EAMQ,KAAA,wBAAA;EAER,KAAA,oBAAA;CACP;CAEH,UAAgB;EACf,KAAK,UAAU,SAAQ,MAAK,EAAE,QAAQ,CAAC;EACvC,KAAK,UAAU,MAAM;CACtB;;;;;;CAOA,yBACC,SACA,QACmB;EACnB,OAAO,KAAK,sBAAsB,CAAC,CAAC,yBAAyB,SAAS,MAAM;CAC7E;;;;;;CAOA,YAAY,QAA4D;EACvE,OAAO,KAAK,sBAAsB,CAAC,CAAC,YAAY,MAAM;CACvD;;CAGA,gBAAgB,aAA8F;EAC7G,OAAO,KAAK,sBAAsB,CAAC,CAAC,gBAAgB,WAAW;CAChE;;CAGA,IAAI,OAAmB;EACtB,OAAO,KAAK,sBAAsB,CAAC,CAAC;CACrC;CAEA,MAAM,IAAI,YAAwE;EACjF,OAAO,KAAK,eAAe,UAAU;CACtC;CAEA,MACM,QAAuB;EAE5B,MAAM,QAAQ,WACb,wBAAwB,IAAI,OAAM,gBAChC,MAAM,KAAK,eAAe,UAAU,EAAA,CAAG,kBAAkB,CAC3D,CACD;CACD;CAEA,SAAS,YAA6B;EAIrC,QAAQ,YAAR;GACC,KAAA;GACA,KAAA;GACA,KAAA;GACA,KAAA;GACA,KAAA;GACA,KAAA;GACA,KAAA;GACA,KAAA;GACA,KAAA,UACC,OAAO;GACR,SACC,OAAO;EACT;CACD;CAEA,MACc,eAAe,YAAwE;EACpG,IAAI,WAAW,KAAK,UAAU,IAAI,UAAU;EAC5C,IAAI,YAAY,MAAM,OAAO;EAI7B,MAAM,eAAe,MAAM,KAAK,IAAI,OAAO,+BAA+B,EACzE,IAAI,WACL,CAAC;EACD,IAAI,gBAAgB,MAAM;GACzB,WAAW,IAAI,+BACd,cACA,+BAA+B,UAAU,IACxC,aAAa,YACb,KAAK,sBAAsB,CAAC,CAAC,oBAAoB,YAAY,aAAa,OAAO,CACnF;GACA,KAAK,UAAU,IAAI,YAAY,QAAQ;GACvC,OAAO;EACR;EAGA,QAAQ,YAAR;GACC,KAAA;GACA,KAAA;GACA,KAAA;GACA,KAAA;GACA,KAAA;GACA,KAAA;GACA,KAAA;GACA,KAAA;GACA,KAAA;GACA,KAAA;GACA,KAAA;GACA,KAAA;IACC,WAAW,IAAI,uCACd,MACA,KAAK,8BACL,UACD;IACA;GACD,SACC,MAAM,IAAI,MAAM,0DAA0D,OAAO,UAAU,EAAE,EAAE;EACjG;EAEA,KAAK,UAAU,IAAI,YAAY,QAAQ;EACvC,OAAO;CACR;AACD;AA9EE,WAAA,CAAA,MAAM,CAAA,GAAA,iCAAA,WAAA,SAAA,IAAA;AA8BN,WAAA,CAAA,KAAK,CAAA,GAAA,iCAAA,WAAA,kBAAA,IAAA"}
@@ -34,6 +34,15 @@ export interface ProviderAuthenticationSession extends AuthenticationSessionLike
34
34
  /** The provider app key paired with the token for providers whose client needs one (e.g. Trello). */
35
35
  readonly appKey?: string;
36
36
  }
37
+ export type SessionPublication = {
38
+ readonly session?: ProviderAuthenticationSession;
39
+ readonly previousSessionId?: string;
40
+ readonly connectionId?: string;
41
+ /** A removal has no session from which to recover the affected storage variant. */
42
+ readonly cloud?: boolean;
43
+ readonly replacePrimary?: boolean;
44
+ };
45
+ export declare function getSessionIdentity(session: Partial<Pick<ProviderAuthenticationSession, 'id' | 'accessToken' | 'domain' | 'baseUrl' | 'protocol' | 'appKey' | 'type' | 'cloud'>> | null | undefined): string | undefined;
37
46
  export interface TokenInfo<T extends IntegrationIds | 'gitkraken' = IntegrationIds | 'gitkraken'> {
38
47
  readonly providerId: T;
39
48
  /**
@@ -1,6 +1,18 @@
1
1
  import { microhash } from "../../../utils/hash.js";
2
2
  import { IssuesCloudHostIntegrationId, supportedOrderedCloudIntegrationIds } from "../constants.js";
3
3
  //#region ../plus/integrations/src/authentication/models.ts
4
+ function getSessionIdentity(session) {
5
+ return session == null ? void 0 : JSON.stringify([
6
+ session.id,
7
+ session.accessToken,
8
+ session.domain,
9
+ session.baseUrl,
10
+ session.protocol,
11
+ session.appKey,
12
+ session.type,
13
+ session.cloud
14
+ ]);
15
+ }
4
16
  function toTokenInfo(providerId, accessToken, info) {
5
17
  return {
6
18
  providerId,
@@ -60,6 +72,6 @@ const toCloudIntegrationType = {
60
72
  ["bitbucket-server"]: "bitbucketServer"
61
73
  };
62
74
  //#endregion
63
- export { CloudIntegrationAuthenticationUriPathPrefix, getSupportedCloudIntegrationIds, isIssueCloudIntegrationId, isSupportedCloudIntegrationId, toCloudIntegrationType, toIntegrationId, toTokenInfo, toTokenWithInfo };
75
+ export { CloudIntegrationAuthenticationUriPathPrefix, getSessionIdentity, getSupportedCloudIntegrationIds, isIssueCloudIntegrationId, isSupportedCloudIntegrationId, toCloudIntegrationType, toIntegrationId, toTokenInfo, toTokenWithInfo };
64
76
 
65
77
  //# sourceMappingURL=models.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"models.js","names":[],"sources":["../../../../../plus/integrations/src/authentication/models.ts"],"sourcesContent":["import { microhash } from '@gitlens/utils/hash.js';\nimport type { IntegrationIds, SupportedCloudIntegrationIds } from '../constants.js';\nimport {\n\tGitCloudHostIntegrationId,\n\tGitSelfManagedHostIntegrationId,\n\tIssuesCloudHostIntegrationId,\n\tIssuesSelfManagedHostIntegrationId,\n\tsupportedOrderedCloudIntegrationIds,\n} from '../constants.js';\n\n/**\n * Mirrors the shape of `vscode.AuthenticationSession` so the integrations\n * package can stay vscode-free. Host adapters bridge VS Code sessions to\n * this shape via {@link AuthenticationProvider}.\n */\nexport interface AuthenticationSessionLike {\n\treadonly id: string;\n\treadonly accessToken: string;\n\treadonly account: { readonly id: string; readonly label: string };\n\treadonly scopes: readonly string[];\n}\n\nexport interface ProviderAuthenticationSession extends AuthenticationSessionLike {\n\treadonly cloud: boolean;\n\treadonly type: CloudIntegrationAuthType | undefined;\n\treadonly expiresAt?: Date;\n\treadonly domain: string;\n\t/**\n\t * The connection's address exactly as it was configured, path and all, when that differs from\n\t * {@link domain}.\n\t *\n\t * `domain` is the IDENTITY a self-managed connection is keyed by, so it is normalized to a bare host\n\t * (`hostFromDomain`) and one host cannot key two connections. An instance mounted below a context path —\n\t * Jira Data Center's `/jira`, a reverse-proxied GitLab or Bitbucket — still has to be ADDRESSED at that\n\t * path, and normalizing it away is what made every request go to the root. Absent when the backend\n\t * reported nothing beyond the host, which is the common case.\n\t */\n\treadonly baseUrl?: string;\n\treadonly protocol?: string;\n\t/** The provider app key paired with the token for providers whose client needs one (e.g. Trello). */\n\treadonly appKey?: string;\n}\n\nexport interface TokenInfo<T extends IntegrationIds | 'gitkraken' = IntegrationIds | 'gitkraken'> {\n\treadonly providerId: T;\n\t/**\n\t * The first 3 characters of the md5 hash of the token.\n\t * It's a very obfuscated representation of the token that we can use in logs\n\t * to see whether the token survives refreshing or gets updated.\n\t */\n\treadonly microHash: string | undefined;\n\treadonly cloud: boolean;\n\treadonly type: CloudIntegrationAuthType | undefined;\n\treadonly scopes: readonly string[] | undefined;\n\treadonly expiresAt?: Date;\n}\n\nexport interface TokenWithInfo<T extends IntegrationIds = IntegrationIds> extends TokenInfo<T> {\n\treadonly accessToken: string;\n}\n\nexport function toTokenInfo<T extends IntegrationIds | 'gitkraken'>(\n\tproviderId: T,\n\taccessToken: string | undefined,\n\tinfo: { cloud: boolean; type: CloudIntegrationAuthType | undefined; scopes?: readonly string[]; expiresAt?: Date },\n): TokenInfo<T> {\n\treturn {\n\t\tproviderId: providerId,\n\t\tmicroHash: microhash(accessToken, 3),\n\t\tcloud: info.cloud,\n\t\ttype: info.type,\n\t\tscopes: info.scopes,\n\t\texpiresAt: info.expiresAt,\n\t};\n}\n\nexport function toTokenWithInfo<T extends IntegrationIds>(\n\tproviderId: T,\n\tsession: ProviderAuthenticationSession,\n\taltToken?: string,\n): TokenWithInfo<T> {\n\tconst { accessToken: sessionToken, ...sessionInfo } = session;\n\tconst accessToken = altToken ?? session.accessToken;\n\treturn {\n\t\t// pass original token info to form the correlated microhash\n\t\t...toTokenInfo(providerId, sessionToken, sessionInfo),\n\t\t// use the actual token used for the request\n\t\taccessToken: accessToken,\n\t};\n}\n\nexport type TokenOptInfo<T extends IntegrationIds = IntegrationIds> =\n\t| TokenWithInfo<T>\n\t// `connectionId` targets a specific connection (multi-account) when the token still has to be resolved.\n\t// Omitted resolves the provider's primary connection, preserving the pre-multi-account behavior.\n\t| { providerId: T; accessToken?: undefined; connectionId?: string };\n\nexport interface ConfiguredIntegrationDescriptor {\n\t/**\n\t * Stable per-connection identifier, distinct from the domain, so multiple accounts can be\n\t * connected to the same provider+domain simultaneously. For legacy/migrated single connections\n\t * this is the domain (self-managed) or the provider's canonical domain (cloud), which keeps the\n\t * existing secret key (`integration.auth[.cloud]:{id}|{domain}`) valid with zero migration.\n\t */\n\treadonly id: string;\n\t/**\n\t * Whether this is the connection used by default for the provider. Optional: when no descriptor\n\t * for a provider+domain carries an explicit flag, the first one is treated as primary. Only\n\t * {@link ConfiguredIntegrationService.setPrimaryConnection} sets the flag (and clears it on siblings).\n\t */\n\treadonly primary?: boolean;\n\t/** The connection's auth type (`oauth`/`pat`), when known. */\n\treadonly type?: CloudIntegrationAuthType;\n\t/**\n\t * Human-readable account handle for this connection (e.g. the GitHub login). Resolved from the\n\t * provider API (the token backend doesn't expose it); absent until resolved or if the lookup fails.\n\t */\n\treadonly accountName?: string;\n\t/**\n\t * Workspace the connection's token was granted for (Linear), separate from the person. Resolved with the\n\t * connection's own token and kept by connection id; both are set together, or neither is.\n\t */\n\treadonly resourceName?: string;\n\treadonly resourceId?: string;\n\treadonly cloud: boolean;\n\treadonly integrationId: IntegrationIds;\n\treadonly scopes: string;\n\treadonly domain?: string;\n\t/**\n\t * The address this connection was configured with, path included — see\n\t * {@link ProviderAuthenticationSession.baseUrl}.\n\t *\n\t * Mirrored onto the descriptor so reconciliation can tell a re-pointed connection from an unchanged one\n\t * without reading its secret: {@link domain} is normalized to a bare host, so a backend connection moved\n\t * from one context path to another on the SAME host looks identical by domain alone.\n\t */\n\treadonly baseUrl?: string;\n\treadonly expiresAt?: string | Date;\n}\n\nexport interface CloudIntegrationAuthenticationSession {\n\ttype: CloudIntegrationAuthType;\n\taccessToken: string;\n\tdomain: string;\n\texpiresIn: number;\n\tscopes: string;\n\t/** Backend per-connection token identifier, when the provider-tokens backend supports multi-account. */\n\tid?: string;\n\t/** Provider app key paired with the token (e.g. Trello app key), when the backend supplies one. */\n\tappKey?: string;\n}\n\nexport interface CloudIntegrationAuthorization {\n\turl: string;\n}\n\n/** Workspace a connection's token was granted for; only ever a complete pair. */\nexport interface ConnectionResource {\n\treadonly id: string;\n\treadonly name: string;\n}\n\nexport interface CloudIntegrationConnection {\n\ttype: CloudIntegrationAuthType;\n\tprovider: CloudIntegrationType;\n\tdomain: string;\n\t/** Backend per-connection token identifier, when the provider-tokens backend supports multi-account. */\n\tid?: string;\n\t/** Whether the backend marks this connection as the primary/default for the provider. */\n\tprimary?: boolean;\n\t/** Human-readable account handle, when the backend provides it on the connection (may be absent). */\n\taccountName?: string;\n}\n\nexport type CloudIntegrationType =\n\t| 'jira'\n\t| 'jiraServer'\n\t| 'linear'\n\t| 'trello'\n\t| 'gitlab'\n\t| 'github'\n\t| 'bitbucket'\n\t| 'bitbucketServer'\n\t| 'azure'\n\t| 'azureDevopsServer'\n\t| 'githubEnterprise'\n\t| 'gitlabSelfHosted';\n\nexport type CloudIntegrationAuthType = 'oauth' | 'pat';\n\nexport const CloudIntegrationAuthenticationUriPathPrefix = 'did-authenticate-cloud-integration';\n\n/** Returns all supported cloud integration ids. */\nexport function getSupportedCloudIntegrationIds(): readonly SupportedCloudIntegrationIds[] {\n\t// Return the shared const directly (readonly so callers can't mutate it) — this runs on hot,\n\t// per-integration membership paths, so avoid allocating a fresh array per call.\n\treturn supportedOrderedCloudIntegrationIds;\n}\n\n/** Whether `id` is a supported cloud integration id. */\nexport function isSupportedCloudIntegrationId(id: string): id is SupportedCloudIntegrationIds {\n\treturn getSupportedCloudIntegrationIds().includes(id as SupportedCloudIntegrationIds);\n}\n\nexport function isIssueCloudIntegrationId(id: string): id is IssuesCloudHostIntegrationId {\n\tconst issueIds: string[] = Object.values(IssuesCloudHostIntegrationId);\n\treturn issueIds.includes(id);\n}\n\nexport const toIntegrationId: { [key in CloudIntegrationType]: IntegrationIds } = {\n\tjira: IssuesCloudHostIntegrationId.Jira,\n\tjiraServer: IssuesSelfManagedHostIntegrationId.JiraServer,\n\tlinear: IssuesCloudHostIntegrationId.Linear,\n\ttrello: IssuesCloudHostIntegrationId.Trello,\n\tgitlab: GitCloudHostIntegrationId.GitLab,\n\tgithub: GitCloudHostIntegrationId.GitHub,\n\tgithubEnterprise: GitSelfManagedHostIntegrationId.CloudGitHubEnterprise,\n\tgitlabSelfHosted: GitSelfManagedHostIntegrationId.CloudGitLabSelfHosted,\n\tbitbucket: GitCloudHostIntegrationId.Bitbucket,\n\tbitbucketServer: GitSelfManagedHostIntegrationId.BitbucketServer,\n\tazure: GitCloudHostIntegrationId.AzureDevOps,\n\tazureDevopsServer: GitSelfManagedHostIntegrationId.AzureDevOpsServer,\n};\n\nexport const toCloudIntegrationType: { [key in IntegrationIds]: CloudIntegrationType | undefined } = {\n\t[IssuesCloudHostIntegrationId.Jira]: 'jira',\n\t[IssuesSelfManagedHostIntegrationId.JiraServer]: 'jiraServer',\n\t[IssuesCloudHostIntegrationId.Linear]: 'linear',\n\t[IssuesCloudHostIntegrationId.Trello]: 'trello',\n\t[GitCloudHostIntegrationId.GitLab]: 'gitlab',\n\t[GitCloudHostIntegrationId.GitHub]: 'github',\n\t[GitCloudHostIntegrationId.Bitbucket]: 'bitbucket',\n\t[GitCloudHostIntegrationId.AzureDevOps]: 'azure',\n\t[GitSelfManagedHostIntegrationId.AzureDevOpsServer]: 'azureDevopsServer',\n\t[GitSelfManagedHostIntegrationId.CloudGitHubEnterprise]: 'githubEnterprise',\n\t[GitSelfManagedHostIntegrationId.CloudGitLabSelfHosted]: 'gitlabSelfHosted',\n\t[GitSelfManagedHostIntegrationId.BitbucketServer]: 'bitbucketServer',\n};\n"],"mappings":";;;AA6DA,SAAgB,YACf,YACA,aACA,MACe;CACf,OAAO;EACM;EACZ,WAAW,UAAU,aAAa,CAAC;EACnC,OAAO,KAAK;EACZ,MAAM,KAAK;EACX,QAAQ,KAAK;EACb,WAAW,KAAK;CACjB;AACD;AAEA,SAAgB,gBACf,YACA,SACA,UACmB;CACnB,MAAM,EAAE,aAAa,cAAc,GAAG,gBAAgB;CACtD,MAAM,cAAc,YAAY,QAAQ;CACxC,OAAO;EAEN,GAAG,YAAY,YAAY,cAAc,WAAW;EAEvC;CACd;AACD;AAqGA,MAAa,8CAA8C;;AAG3D,SAAgB,kCAA2E;CAG1F,OAAO;AACR;;AAGA,SAAgB,8BAA8B,IAAgD;CAC7F,OAAO,gCAAgC,CAAC,CAAC,SAAS,EAAkC;AACrF;AAEA,SAAgB,0BAA0B,IAAgD;CAEzF,OAD2B,OAAO,OAAO,4BAC3B,CAAC,CAAC,SAAS,EAAE;AAC5B;AAEA,MAAa,kBAAqE;CACjF,MAAA;CACA,YAAA;CACA,QAAA;CACA,QAAA;CACA,QAAA;CACA,QAAA;CACA,kBAAA;CACA,kBAAA;CACA,WAAA;CACA,iBAAA;CACA,OAAA;CACA,mBAAA;AACD;AAEA,MAAa,yBAAwF;EAC/D,SAAA;EACY,gBAAA;EACV,WAAA;EACA,WAAA;EACH,WAAA;EACA,WAAA;EACG,cAAA;EACE,gBAAA;EACY,wBAAA;EACI,4BAAA;EACA,6BAAA;EACN,qBAAA;AACpD"}
1
+ {"version":3,"file":"models.js","names":[],"sources":["../../../../../plus/integrations/src/authentication/models.ts"],"sourcesContent":["import { microhash } from '@gitlens/utils/hash.js';\nimport type { IntegrationIds, SupportedCloudIntegrationIds } from '../constants.js';\nimport {\n\tGitCloudHostIntegrationId,\n\tGitSelfManagedHostIntegrationId,\n\tIssuesCloudHostIntegrationId,\n\tIssuesSelfManagedHostIntegrationId,\n\tsupportedOrderedCloudIntegrationIds,\n} from '../constants.js';\n\n/**\n * Mirrors the shape of `vscode.AuthenticationSession` so the integrations\n * package can stay vscode-free. Host adapters bridge VS Code sessions to\n * this shape via {@link AuthenticationProvider}.\n */\nexport interface AuthenticationSessionLike {\n\treadonly id: string;\n\treadonly accessToken: string;\n\treadonly account: { readonly id: string; readonly label: string };\n\treadonly scopes: readonly string[];\n}\n\nexport interface ProviderAuthenticationSession extends AuthenticationSessionLike {\n\treadonly cloud: boolean;\n\treadonly type: CloudIntegrationAuthType | undefined;\n\treadonly expiresAt?: Date;\n\treadonly domain: string;\n\t/**\n\t * The connection's address exactly as it was configured, path and all, when that differs from\n\t * {@link domain}.\n\t *\n\t * `domain` is the IDENTITY a self-managed connection is keyed by, so it is normalized to a bare host\n\t * (`hostFromDomain`) and one host cannot key two connections. An instance mounted below a context path —\n\t * Jira Data Center's `/jira`, a reverse-proxied GitLab or Bitbucket — still has to be ADDRESSED at that\n\t * path, and normalizing it away is what made every request go to the root. Absent when the backend\n\t * reported nothing beyond the host, which is the common case.\n\t */\n\treadonly baseUrl?: string;\n\treadonly protocol?: string;\n\t/** The provider app key paired with the token for providers whose client needs one (e.g. Trello). */\n\treadonly appKey?: string;\n}\n\nexport type SessionPublication = {\n\treadonly session?: ProviderAuthenticationSession;\n\treadonly previousSessionId?: string;\n\treadonly connectionId?: string;\n\t/** A removal has no session from which to recover the affected storage variant. */\n\treadonly cloud?: boolean;\n\treadonly replacePrimary?: boolean;\n};\n\nexport function getSessionIdentity(\n\tsession:\n\t\t| Partial<\n\t\t\t\tPick<\n\t\t\t\t\tProviderAuthenticationSession,\n\t\t\t\t\t'id' | 'accessToken' | 'domain' | 'baseUrl' | 'protocol' | 'appKey' | 'type' | 'cloud'\n\t\t\t\t>\n\t\t >\n\t\t| null\n\t\t| undefined,\n): string | undefined {\n\treturn session == null\n\t\t? undefined\n\t\t: JSON.stringify([\n\t\t\t\tsession.id,\n\t\t\t\tsession.accessToken,\n\t\t\t\tsession.domain,\n\t\t\t\tsession.baseUrl,\n\t\t\t\tsession.protocol,\n\t\t\t\tsession.appKey,\n\t\t\t\tsession.type,\n\t\t\t\tsession.cloud,\n\t\t\t]);\n}\n\nexport interface TokenInfo<T extends IntegrationIds | 'gitkraken' = IntegrationIds | 'gitkraken'> {\n\treadonly providerId: T;\n\t/**\n\t * The first 3 characters of the md5 hash of the token.\n\t * It's a very obfuscated representation of the token that we can use in logs\n\t * to see whether the token survives refreshing or gets updated.\n\t */\n\treadonly microHash: string | undefined;\n\treadonly cloud: boolean;\n\treadonly type: CloudIntegrationAuthType | undefined;\n\treadonly scopes: readonly string[] | undefined;\n\treadonly expiresAt?: Date;\n}\n\nexport interface TokenWithInfo<T extends IntegrationIds = IntegrationIds> extends TokenInfo<T> {\n\treadonly accessToken: string;\n}\n\nexport function toTokenInfo<T extends IntegrationIds | 'gitkraken'>(\n\tproviderId: T,\n\taccessToken: string | undefined,\n\tinfo: { cloud: boolean; type: CloudIntegrationAuthType | undefined; scopes?: readonly string[]; expiresAt?: Date },\n): TokenInfo<T> {\n\treturn {\n\t\tproviderId: providerId,\n\t\tmicroHash: microhash(accessToken, 3),\n\t\tcloud: info.cloud,\n\t\ttype: info.type,\n\t\tscopes: info.scopes,\n\t\texpiresAt: info.expiresAt,\n\t};\n}\n\nexport function toTokenWithInfo<T extends IntegrationIds>(\n\tproviderId: T,\n\tsession: ProviderAuthenticationSession,\n\taltToken?: string,\n): TokenWithInfo<T> {\n\tconst { accessToken: sessionToken, ...sessionInfo } = session;\n\tconst accessToken = altToken ?? session.accessToken;\n\treturn {\n\t\t// pass original token info to form the correlated microhash\n\t\t...toTokenInfo(providerId, sessionToken, sessionInfo),\n\t\t// use the actual token used for the request\n\t\taccessToken: accessToken,\n\t};\n}\n\nexport type TokenOptInfo<T extends IntegrationIds = IntegrationIds> =\n\t| TokenWithInfo<T>\n\t// `connectionId` targets a specific connection (multi-account) when the token still has to be resolved.\n\t// Omitted resolves the provider's primary connection, preserving the pre-multi-account behavior.\n\t| { providerId: T; accessToken?: undefined; connectionId?: string };\n\nexport interface ConfiguredIntegrationDescriptor {\n\t/**\n\t * Stable per-connection identifier, distinct from the domain, so multiple accounts can be\n\t * connected to the same provider+domain simultaneously. For legacy/migrated single connections\n\t * this is the domain (self-managed) or the provider's canonical domain (cloud), which keeps the\n\t * existing secret key (`integration.auth[.cloud]:{id}|{domain}`) valid with zero migration.\n\t */\n\treadonly id: string;\n\t/**\n\t * Whether this is the connection used by default for the provider. Optional: when no descriptor\n\t * for a provider+domain carries an explicit flag, the first one is treated as primary. Only\n\t * {@link ConfiguredIntegrationService.setPrimaryConnection} sets the flag (and clears it on siblings).\n\t */\n\treadonly primary?: boolean;\n\t/** The connection's auth type (`oauth`/`pat`), when known. */\n\treadonly type?: CloudIntegrationAuthType;\n\t/**\n\t * Human-readable account handle for this connection (e.g. the GitHub login). Resolved from the\n\t * provider API (the token backend doesn't expose it); absent until resolved or if the lookup fails.\n\t */\n\treadonly accountName?: string;\n\t/**\n\t * Workspace the connection's token was granted for (Linear), separate from the person. Resolved with the\n\t * connection's own token and kept by connection id; both are set together, or neither is.\n\t */\n\treadonly resourceName?: string;\n\treadonly resourceId?: string;\n\treadonly cloud: boolean;\n\treadonly integrationId: IntegrationIds;\n\treadonly scopes: string;\n\treadonly domain?: string;\n\t/**\n\t * The address this connection was configured with, path included — see\n\t * {@link ProviderAuthenticationSession.baseUrl}.\n\t *\n\t * Mirrored onto the descriptor so reconciliation can tell a re-pointed connection from an unchanged one\n\t * without reading its secret: {@link domain} is normalized to a bare host, so a backend connection moved\n\t * from one context path to another on the SAME host looks identical by domain alone.\n\t */\n\treadonly baseUrl?: string;\n\treadonly expiresAt?: string | Date;\n}\n\nexport interface CloudIntegrationAuthenticationSession {\n\ttype: CloudIntegrationAuthType;\n\taccessToken: string;\n\tdomain: string;\n\texpiresIn: number;\n\tscopes: string;\n\t/** Backend per-connection token identifier, when the provider-tokens backend supports multi-account. */\n\tid?: string;\n\t/** Provider app key paired with the token (e.g. Trello app key), when the backend supplies one. */\n\tappKey?: string;\n}\n\nexport interface CloudIntegrationAuthorization {\n\turl: string;\n}\n\n/** Workspace a connection's token was granted for; only ever a complete pair. */\nexport interface ConnectionResource {\n\treadonly id: string;\n\treadonly name: string;\n}\n\nexport interface CloudIntegrationConnection {\n\ttype: CloudIntegrationAuthType;\n\tprovider: CloudIntegrationType;\n\tdomain: string;\n\t/** Backend per-connection token identifier, when the provider-tokens backend supports multi-account. */\n\tid?: string;\n\t/** Whether the backend marks this connection as the primary/default for the provider. */\n\tprimary?: boolean;\n\t/** Human-readable account handle, when the backend provides it on the connection (may be absent). */\n\taccountName?: string;\n}\n\nexport type CloudIntegrationType =\n\t| 'jira'\n\t| 'jiraServer'\n\t| 'linear'\n\t| 'trello'\n\t| 'gitlab'\n\t| 'github'\n\t| 'bitbucket'\n\t| 'bitbucketServer'\n\t| 'azure'\n\t| 'azureDevopsServer'\n\t| 'githubEnterprise'\n\t| 'gitlabSelfHosted';\n\nexport type CloudIntegrationAuthType = 'oauth' | 'pat';\n\nexport const CloudIntegrationAuthenticationUriPathPrefix = 'did-authenticate-cloud-integration';\n\n/** Returns all supported cloud integration ids. */\nexport function getSupportedCloudIntegrationIds(): readonly SupportedCloudIntegrationIds[] {\n\t// Return the shared const directly (readonly so callers can't mutate it) — this runs on hot,\n\t// per-integration membership paths, so avoid allocating a fresh array per call.\n\treturn supportedOrderedCloudIntegrationIds;\n}\n\n/** Whether `id` is a supported cloud integration id. */\nexport function isSupportedCloudIntegrationId(id: string): id is SupportedCloudIntegrationIds {\n\treturn getSupportedCloudIntegrationIds().includes(id as SupportedCloudIntegrationIds);\n}\n\nexport function isIssueCloudIntegrationId(id: string): id is IssuesCloudHostIntegrationId {\n\tconst issueIds: string[] = Object.values(IssuesCloudHostIntegrationId);\n\treturn issueIds.includes(id);\n}\n\nexport const toIntegrationId: { [key in CloudIntegrationType]: IntegrationIds } = {\n\tjira: IssuesCloudHostIntegrationId.Jira,\n\tjiraServer: IssuesSelfManagedHostIntegrationId.JiraServer,\n\tlinear: IssuesCloudHostIntegrationId.Linear,\n\ttrello: IssuesCloudHostIntegrationId.Trello,\n\tgitlab: GitCloudHostIntegrationId.GitLab,\n\tgithub: GitCloudHostIntegrationId.GitHub,\n\tgithubEnterprise: GitSelfManagedHostIntegrationId.CloudGitHubEnterprise,\n\tgitlabSelfHosted: GitSelfManagedHostIntegrationId.CloudGitLabSelfHosted,\n\tbitbucket: GitCloudHostIntegrationId.Bitbucket,\n\tbitbucketServer: GitSelfManagedHostIntegrationId.BitbucketServer,\n\tazure: GitCloudHostIntegrationId.AzureDevOps,\n\tazureDevopsServer: GitSelfManagedHostIntegrationId.AzureDevOpsServer,\n};\n\nexport const toCloudIntegrationType: { [key in IntegrationIds]: CloudIntegrationType | undefined } = {\n\t[IssuesCloudHostIntegrationId.Jira]: 'jira',\n\t[IssuesSelfManagedHostIntegrationId.JiraServer]: 'jiraServer',\n\t[IssuesCloudHostIntegrationId.Linear]: 'linear',\n\t[IssuesCloudHostIntegrationId.Trello]: 'trello',\n\t[GitCloudHostIntegrationId.GitLab]: 'gitlab',\n\t[GitCloudHostIntegrationId.GitHub]: 'github',\n\t[GitCloudHostIntegrationId.Bitbucket]: 'bitbucket',\n\t[GitCloudHostIntegrationId.AzureDevOps]: 'azure',\n\t[GitSelfManagedHostIntegrationId.AzureDevOpsServer]: 'azureDevopsServer',\n\t[GitSelfManagedHostIntegrationId.CloudGitHubEnterprise]: 'githubEnterprise',\n\t[GitSelfManagedHostIntegrationId.CloudGitLabSelfHosted]: 'gitlabSelfHosted',\n\t[GitSelfManagedHostIntegrationId.BitbucketServer]: 'bitbucketServer',\n};\n"],"mappings":";;;AAoDA,SAAgB,mBACf,SASqB;CACrB,OAAO,WAAW,OACf,KAAA,IACA,KAAK,UAAU;EACf,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;CACT,CAAC;AACJ;AAoBA,SAAgB,YACf,YACA,aACA,MACe;CACf,OAAO;EACM;EACZ,WAAW,UAAU,aAAa,CAAC;EACnC,OAAO,KAAK;EACZ,MAAM,KAAK;EACX,QAAQ,KAAK;EACb,WAAW,KAAK;CACjB;AACD;AAEA,SAAgB,gBACf,YACA,SACA,UACmB;CACnB,MAAM,EAAE,aAAa,cAAc,GAAG,gBAAgB;CACtD,MAAM,cAAc,YAAY,QAAQ;CACxC,OAAO;EAEN,GAAG,YAAY,YAAY,cAAc,WAAW;EAEvC;CACd;AACD;AAqGA,MAAa,8CAA8C;;AAG3D,SAAgB,kCAA2E;CAG1F,OAAO;AACR;;AAGA,SAAgB,8BAA8B,IAAgD;CAC7F,OAAO,gCAAgC,CAAC,CAAC,SAAS,EAAkC;AACrF;AAEA,SAAgB,0BAA0B,IAAgD;CAEzF,OAD2B,OAAO,OAAO,4BAC3B,CAAC,CAAC,SAAS,EAAE;AAC5B;AAEA,MAAa,kBAAqE;CACjF,MAAA;CACA,YAAA;CACA,QAAA;CACA,QAAA;CACA,QAAA;CACA,QAAA;CACA,kBAAA;CACA,kBAAA;CACA,WAAA;CACA,iBAAA;CACA,OAAA;CACA,mBAAA;AACD;AAEA,MAAa,yBAAwF;EAC/D,SAAA;EACY,gBAAA;EACV,WAAA;EACA,WAAA;EACH,WAAA;EACA,WAAA;EACG,cAAA;EACE,gBAAA;EACY,wBAAA;EACI,4BAAA;EACA,6BAAA;EACN,qBAAA;AACpD"}
@@ -0,0 +1,34 @@
1
+ import { Event } from "../../../utils/event.js";
2
+ import { ProviderAuthenticationSession, SessionPublication } from "./models.js";
3
+ import { GetSessionOptions, IntegrationAuthenticationProvider, IntegrationAuthenticationSessionDescriptor } from "./integrationAuthenticationProvider.js";
4
+ //#region ../plus/integrations/src/authentication/observedAuthenticationProvider.d.ts
5
+ export declare class ObservedAuthenticationProvider implements IntegrationAuthenticationProvider {
6
+ private readonly host;
7
+ private readonly selfManaged;
8
+ private readonly publish;
9
+ private readonly observations;
10
+ private readonly credentials;
11
+ private readonly descriptorRetirements;
12
+ private readonly actualRetirements;
13
+ private readonly hostRetirements;
14
+ private readonly activeRetirements;
15
+ private sequence;
16
+ private globalRetirement;
17
+ private disposed;
18
+ constructor(host: IntegrationAuthenticationProvider, selfManaged: boolean, publish: (publication: SessionPublication, domains: (string | undefined)[]) => void);
19
+ get onDidChange(): Event<void>;
20
+ getSession(descriptor: IntegrationAuthenticationSessionDescriptor, options?: GetSessionOptions): Promise<ProviderAuthenticationSession | undefined>;
21
+ deleteSession(descriptor: IntegrationAuthenticationSessionDescriptor, options?: {
22
+ preserveConfigured?: boolean;
23
+ }): Promise<void>;
24
+ deleteAllSessions(descriptor?: IntegrationAuthenticationSessionDescriptor): Promise<void>;
25
+ dispose(): void;
26
+ private isRetired;
27
+ private retireConnection;
28
+ private retireAll;
29
+ private addTarget;
30
+ private removeTargets;
31
+ private markRetirement;
32
+ }
33
+ //#endregion
34
+ //# sourceMappingURL=observedAuthenticationProvider.d.ts.map