@gitkraken/core-gitlens 0.21.0 → 0.22.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -1
- package/dist/git/utils/autolink.utils.d.ts +4 -1
- package/dist/git/utils/autolink.utils.js +12 -3
- package/dist/git/utils/autolink.utils.js.map +1 -1
- package/dist/plus/integrations/authentication/configuredIntegrationService.d.ts +7 -0
- package/dist/plus/integrations/authentication/configuredIntegrationService.js +12 -0
- package/dist/plus/integrations/authentication/configuredIntegrationService.js.map +1 -1
- package/dist/plus/integrations/authentication/integrationAuthenticationService.js +5 -3
- package/dist/plus/integrations/authentication/integrationAuthenticationService.js.map +1 -1
- package/dist/plus/integrations/authentication/models.d.ts +9 -0
- package/dist/plus/integrations/authentication/models.js +13 -1
- package/dist/plus/integrations/authentication/models.js.map +1 -1
- package/dist/plus/integrations/authentication/observedAuthenticationProvider.d.ts +34 -0
- package/dist/plus/integrations/authentication/observedAuthenticationProvider.js +227 -0
- package/dist/plus/integrations/authentication/observedAuthenticationProvider.js.map +1 -0
- package/dist/plus/integrations/index.d.ts +4 -2
- package/dist/plus/integrations/index.js.map +1 -1
- package/dist/plus/integrations/integrationService.d.ts +9 -4
- package/dist/plus/integrations/integrationService.js +30 -7
- package/dist/plus/integrations/integrationService.js.map +1 -1
- package/dist/plus/integrations/manager.d.ts +18 -1
- package/dist/plus/integrations/models/integration.d.ts +8 -1
- package/dist/plus/integrations/models/integration.js +79 -10
- package/dist/plus/integrations/models/integration.js.map +1 -1
- package/dist/plus/integrations/models/issuesIntegration.d.ts +20 -1
- package/dist/plus/integrations/models/issuesIntegration.js +106 -2
- package/dist/plus/integrations/models/issuesIntegration.js.map +1 -1
- package/dist/plus/integrations/providers/issueSorts.d.ts +0 -1
- package/dist/plus/integrations/providers/jira-server.d.ts +10 -2
- package/dist/plus/integrations/providers/jira-server.js +74 -7
- package/dist/plus/integrations/providers/jira-server.js.map +1 -1
- package/dist/plus/integrations/providers/jira.d.ts +3 -3
- package/dist/plus/integrations/providers/jira.js +5 -27
- package/dist/plus/integrations/providers/jira.js.map +1 -1
- package/dist/plus/integrations/providers/linear.d.ts +1 -1
- package/dist/plus/integrations/providers/linear.js +3 -27
- package/dist/plus/integrations/providers/linear.js.map +1 -1
- package/dist/plus/integrations/providers/providerApiClient.js +4 -1
- package/dist/plus/integrations/providers/providerApiClient.js.map +1 -1
- package/dist/plus/integrations/providers/providerErrors.d.ts +4 -1
- package/dist/plus/integrations/providers/providerErrors.js +13 -4
- package/dist/plus/integrations/providers/providerErrors.js.map +1 -1
- package/dist/plus/integrations/providers/providersApi.js +1 -1
- package/dist/plus/integrations/providers/providersApi.js.map +1 -1
- package/dist/plus/integrations/providers/trello.d.ts +1 -1
- package/dist/plus/integrations/providers/trello.js +1 -1
- package/dist/plus/integrations/providers/trello.js.map +1 -1
- package/dist/plus/integrations/providers/utils/issueAutolinks.d.ts +8 -0
- package/dist/plus/integrations/providers/utils/issueAutolinks.js +20 -0
- package/dist/plus/integrations/providers/utils/issueAutolinks.js.map +1 -0
- package/dist/plus/integrations/reads/autolinks.d.ts +7 -0
- package/dist/plus/integrations/reads/autolinks.js +40 -0
- package/dist/plus/integrations/reads/autolinks.js.map +1 -0
- package/dist/plus/integrations/reads/context.d.ts +4 -2
- package/dist/plus/integrations/reads/drains.d.ts +0 -1
- package/dist/plus/integrations/reads/hierarchy.js +1 -1
- package/dist/plus/integrations/reads/issueBatch.js +1 -1
- package/dist/plus/integrations/reads/issueTracker.js +1 -1
- package/dist/plus/integrations/reads/resolveRepository.js +1 -1
- package/docs/integrations.md +22 -1
- package/package.json +1 -1
|
@@ -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
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { CancellationError } from "../../../utils/cancellation.js";
|
|
2
|
+
import { getSessionIdentity } from "./models.js";
|
|
3
|
+
import { areDomainsOnSameHost, hostFromDomain } from "../utils/domain.utils.js";
|
|
4
|
+
//#region ../plus/integrations/src/authentication/observedAuthenticationProvider.ts
|
|
5
|
+
function domainKey(domain) {
|
|
6
|
+
return hostFromDomain(domain) ?? domain;
|
|
7
|
+
}
|
|
8
|
+
function descriptorKey(domain, connectionId, cloud) {
|
|
9
|
+
return JSON.stringify([
|
|
10
|
+
domainKey(domain),
|
|
11
|
+
connectionId,
|
|
12
|
+
cloud
|
|
13
|
+
]);
|
|
14
|
+
}
|
|
15
|
+
function actualKey(domain, id, cloud) {
|
|
16
|
+
return JSON.stringify([
|
|
17
|
+
domainKey(domain),
|
|
18
|
+
id,
|
|
19
|
+
cloud
|
|
20
|
+
]);
|
|
21
|
+
}
|
|
22
|
+
var ObservedAuthenticationProvider = class {
|
|
23
|
+
host;
|
|
24
|
+
selfManaged;
|
|
25
|
+
publish;
|
|
26
|
+
observations = /* @__PURE__ */ new Map();
|
|
27
|
+
credentials = /* @__PURE__ */ new Map();
|
|
28
|
+
descriptorRetirements = /* @__PURE__ */ new Map();
|
|
29
|
+
actualRetirements = /* @__PURE__ */ new Map();
|
|
30
|
+
hostRetirements = /* @__PURE__ */ new Map();
|
|
31
|
+
activeRetirements = /* @__PURE__ */ new Set();
|
|
32
|
+
sequence = 0;
|
|
33
|
+
globalRetirement = 0;
|
|
34
|
+
disposed = false;
|
|
35
|
+
constructor(host, selfManaged, publish) {
|
|
36
|
+
this.host = host;
|
|
37
|
+
this.selfManaged = selfManaged;
|
|
38
|
+
this.publish = publish;
|
|
39
|
+
}
|
|
40
|
+
get onDidChange() {
|
|
41
|
+
return this.host.onDidChange;
|
|
42
|
+
}
|
|
43
|
+
async getSession(descriptor, options) {
|
|
44
|
+
if (this.disposed) return void 0;
|
|
45
|
+
const request = ++this.sequence;
|
|
46
|
+
const scope = JSON.stringify([
|
|
47
|
+
descriptor.connectionId,
|
|
48
|
+
domainKey(descriptor.domain),
|
|
49
|
+
descriptor.cloud,
|
|
50
|
+
descriptor.scopes
|
|
51
|
+
]);
|
|
52
|
+
const source = await this.host.getSession(descriptor, options);
|
|
53
|
+
if (source != null && this.selfManaged && !areDomainsOnSameHost(descriptor.domain, source.domain)) throw new CancellationError();
|
|
54
|
+
if (this.isRetired(request, descriptor, source)) throw new CancellationError();
|
|
55
|
+
const identity = getSessionIdentity(source);
|
|
56
|
+
const previous = this.observations.get(scope);
|
|
57
|
+
const sessionKey = source == null ? previous?.sessionKey ?? (descriptor.connectionId ? actualKey(descriptor.domain, descriptor.connectionId, descriptor.cloud ?? true) : void 0) : actualKey(source.domain || descriptor.domain, source.id, source.cloud);
|
|
58
|
+
const credential = sessionKey == null ? void 0 : this.credentials.get(sessionKey);
|
|
59
|
+
const latest = credential != null && (previous == null || credential.request > previous.request) ? credential : previous;
|
|
60
|
+
if (latest != null && latest.request > request && latest.identity !== identity) throw new CancellationError();
|
|
61
|
+
const session = source == null ? void 0 : {
|
|
62
|
+
id: source.id,
|
|
63
|
+
accessToken: source.accessToken,
|
|
64
|
+
account: source.account,
|
|
65
|
+
scopes: source.scopes,
|
|
66
|
+
cloud: source.cloud,
|
|
67
|
+
type: source.type,
|
|
68
|
+
expiresAt: source.expiresAt,
|
|
69
|
+
domain: source.domain,
|
|
70
|
+
baseUrl: source.baseUrl,
|
|
71
|
+
protocol: source.protocol,
|
|
72
|
+
appKey: source.appKey
|
|
73
|
+
};
|
|
74
|
+
if (latest == null || latest.request <= request) {
|
|
75
|
+
if (previous == null || previous.identity !== identity || credential?.identity !== identity) this.publish({
|
|
76
|
+
session,
|
|
77
|
+
previousSessionId: latest?.sessionId ?? descriptor.connectionId,
|
|
78
|
+
connectionId: descriptor.connectionId,
|
|
79
|
+
cloud: session != null ? session.cloud : latest?.cloud ?? descriptor.cloud,
|
|
80
|
+
replacePrimary: !descriptor.connectionId
|
|
81
|
+
}, [
|
|
82
|
+
descriptor.domain,
|
|
83
|
+
session?.domain,
|
|
84
|
+
previous?.actualDomain
|
|
85
|
+
]);
|
|
86
|
+
const observation = {
|
|
87
|
+
request,
|
|
88
|
+
identity,
|
|
89
|
+
descriptorDomain: descriptor.domain,
|
|
90
|
+
actualDomain: session?.domain || descriptor.domain,
|
|
91
|
+
cloud: session?.cloud ?? descriptor.cloud,
|
|
92
|
+
sessionKey,
|
|
93
|
+
sessionId: source?.id ?? latest?.sessionId ?? descriptor.connectionId,
|
|
94
|
+
connectionId: descriptor.connectionId
|
|
95
|
+
};
|
|
96
|
+
this.observations.set(scope, observation);
|
|
97
|
+
if (sessionKey != null) this.credentials.set(sessionKey, observation);
|
|
98
|
+
}
|
|
99
|
+
return session;
|
|
100
|
+
}
|
|
101
|
+
async deleteSession(descriptor, options) {
|
|
102
|
+
const retirement = this.retireConnection(descriptor);
|
|
103
|
+
this.activeRetirements.add(retirement);
|
|
104
|
+
try {
|
|
105
|
+
await this.host.deleteSession(descriptor, options);
|
|
106
|
+
} finally {
|
|
107
|
+
this.markRetirement(retirement);
|
|
108
|
+
this.activeRetirements.delete(retirement);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
async deleteAllSessions(descriptor) {
|
|
112
|
+
const retirement = this.retireAll(this.selfManaged ? descriptor?.domain : void 0);
|
|
113
|
+
this.activeRetirements.add(retirement);
|
|
114
|
+
try {
|
|
115
|
+
await this.host.deleteAllSessions(descriptor);
|
|
116
|
+
} finally {
|
|
117
|
+
this.markRetirement(retirement);
|
|
118
|
+
this.activeRetirements.delete(retirement);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
dispose() {
|
|
122
|
+
if (this.disposed) return;
|
|
123
|
+
this.disposed = true;
|
|
124
|
+
this.retireAll();
|
|
125
|
+
this.host.dispose();
|
|
126
|
+
}
|
|
127
|
+
isRetired(request, descriptor, session) {
|
|
128
|
+
if (this.disposed || request < this.globalRetirement) return true;
|
|
129
|
+
const host = domainKey(descriptor.domain);
|
|
130
|
+
const variants = /* @__PURE__ */ new Set([
|
|
131
|
+
void 0,
|
|
132
|
+
descriptor.cloud,
|
|
133
|
+
session?.cloud
|
|
134
|
+
]);
|
|
135
|
+
if (descriptor.cloud == null && session?.cloud == null) {
|
|
136
|
+
variants.add(true);
|
|
137
|
+
variants.add(false);
|
|
138
|
+
}
|
|
139
|
+
const descriptorIdentities = Array.from(variants, (cloud) => descriptorKey(descriptor.domain, descriptor.connectionId, cloud));
|
|
140
|
+
const actual = session == null ? void 0 : actualKey(session.domain || descriptor.domain, session.id, session.cloud);
|
|
141
|
+
const actualAnyVariant = session == null ? void 0 : actualKey(session.domain || descriptor.domain, session.id, void 0);
|
|
142
|
+
if (request < (this.hostRetirements.get(host) ?? 0) || descriptorIdentities.some((key) => request < (this.descriptorRetirements.get(key) ?? 0)) || actual != null && request < (this.actualRetirements.get(actual) ?? 0) || actualAnyVariant != null && request < (this.actualRetirements.get(actualAnyVariant) ?? 0)) return true;
|
|
143
|
+
for (const retirement of this.activeRetirements) if (retirement.all || retirement.host === host || descriptorIdentities.some((key) => retirement.descriptors.has(key)) || actual != null && retirement.actuals.has(actual) || actualAnyVariant != null && retirement.actuals.has(actualAnyVariant)) return true;
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
retireConnection(descriptor) {
|
|
147
|
+
const host = domainKey(descriptor.domain);
|
|
148
|
+
const matching = [...this.observations.values()].filter((o) => {
|
|
149
|
+
if (domainKey(o.descriptorDomain) !== host && domainKey(o.actualDomain) !== host) return false;
|
|
150
|
+
if (descriptor.cloud != null && o.cloud !== descriptor.cloud) return false;
|
|
151
|
+
return descriptor.connectionId == null ? o.connectionId == null : o.connectionId === descriptor.connectionId || o.sessionId === descriptor.connectionId;
|
|
152
|
+
});
|
|
153
|
+
const actuals = new Set(matching.filter((o) => o.sessionId != null).map((o) => actualKey(o.actualDomain, o.sessionId, o.cloud)));
|
|
154
|
+
if (descriptor.connectionId != null) actuals.add(actualKey(descriptor.domain, descriptor.connectionId, descriptor.cloud));
|
|
155
|
+
const targets = [...this.observations.values()].filter((o) => {
|
|
156
|
+
if (descriptor.cloud != null && o.cloud !== descriptor.cloud) return false;
|
|
157
|
+
return matching.includes(o) || o.sessionId != null && actuals.has(actualKey(o.actualDomain, o.sessionId, o.cloud));
|
|
158
|
+
});
|
|
159
|
+
const retirement = {
|
|
160
|
+
descriptors: /* @__PURE__ */ new Set(),
|
|
161
|
+
actuals: /* @__PURE__ */ new Set()
|
|
162
|
+
};
|
|
163
|
+
retirement.descriptors.add(descriptorKey(descriptor.domain, descriptor.connectionId, descriptor.cloud));
|
|
164
|
+
if (descriptor.connectionId != null) retirement.actuals.add(actualKey(descriptor.domain, descriptor.connectionId, descriptor.cloud));
|
|
165
|
+
for (const target of targets) {
|
|
166
|
+
this.addTarget(retirement, target);
|
|
167
|
+
this.publish({
|
|
168
|
+
previousSessionId: target.sessionId,
|
|
169
|
+
connectionId: target.connectionId,
|
|
170
|
+
cloud: target.cloud,
|
|
171
|
+
replacePrimary: target.connectionId == null
|
|
172
|
+
}, [target.descriptorDomain, target.actualDomain]);
|
|
173
|
+
}
|
|
174
|
+
if (targets.every((target) => target.connectionId !== descriptor.connectionId)) this.publish({
|
|
175
|
+
previousSessionId: descriptor.connectionId,
|
|
176
|
+
connectionId: descriptor.connectionId,
|
|
177
|
+
cloud: descriptor.cloud,
|
|
178
|
+
replacePrimary: descriptor.connectionId == null
|
|
179
|
+
}, [descriptor.domain]);
|
|
180
|
+
this.removeTargets(targets);
|
|
181
|
+
this.markRetirement(retirement);
|
|
182
|
+
return retirement;
|
|
183
|
+
}
|
|
184
|
+
retireAll(domain) {
|
|
185
|
+
const host = domain == null ? void 0 : domainKey(domain);
|
|
186
|
+
const retirement = {
|
|
187
|
+
descriptors: /* @__PURE__ */ new Set(),
|
|
188
|
+
actuals: /* @__PURE__ */ new Set(),
|
|
189
|
+
host,
|
|
190
|
+
all: host == null
|
|
191
|
+
};
|
|
192
|
+
const targets = [...this.observations.values()].filter((o) => host == null || domainKey(o.descriptorDomain) === host || domainKey(o.actualDomain) === host);
|
|
193
|
+
for (const target of targets) {
|
|
194
|
+
this.addTarget(retirement, target);
|
|
195
|
+
this.publish({
|
|
196
|
+
previousSessionId: target.sessionId,
|
|
197
|
+
connectionId: target.connectionId,
|
|
198
|
+
cloud: target.cloud,
|
|
199
|
+
replacePrimary: target.connectionId == null
|
|
200
|
+
}, [target.descriptorDomain, target.actualDomain]);
|
|
201
|
+
}
|
|
202
|
+
if (targets.length === 0) this.publish({ replacePrimary: true }, [domain]);
|
|
203
|
+
this.removeTargets(targets);
|
|
204
|
+
this.markRetirement(retirement);
|
|
205
|
+
return retirement;
|
|
206
|
+
}
|
|
207
|
+
addTarget(retirement, observation) {
|
|
208
|
+
retirement.descriptors.add(descriptorKey(observation.descriptorDomain, observation.connectionId, observation.cloud));
|
|
209
|
+
if (observation.sessionId != null) retirement.actuals.add(actualKey(observation.actualDomain, observation.sessionId, observation.cloud));
|
|
210
|
+
}
|
|
211
|
+
removeTargets(targets) {
|
|
212
|
+
const removed = new Set(targets);
|
|
213
|
+
for (const [key, observation] of this.observations) if (removed.has(observation)) this.observations.delete(key);
|
|
214
|
+
for (const [key, observation] of this.credentials) if (removed.has(observation)) this.credentials.delete(key);
|
|
215
|
+
}
|
|
216
|
+
markRetirement(retirement) {
|
|
217
|
+
const mark = ++this.sequence;
|
|
218
|
+
if (retirement.all) this.globalRetirement = mark;
|
|
219
|
+
if (retirement.host != null) this.hostRetirements.set(retirement.host, mark);
|
|
220
|
+
for (const key of retirement.descriptors) this.descriptorRetirements.set(key, mark);
|
|
221
|
+
for (const key of retirement.actuals) this.actualRetirements.set(key, mark);
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
//#endregion
|
|
225
|
+
export { ObservedAuthenticationProvider };
|
|
226
|
+
|
|
227
|
+
//# sourceMappingURL=observedAuthenticationProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observedAuthenticationProvider.js","names":[],"sources":["../../../../../plus/integrations/src/authentication/observedAuthenticationProvider.ts"],"sourcesContent":["import { CancellationError } from '@gitlens/utils/cancellation.js';\nimport type { Event } from '@gitlens/utils/event.js';\nimport { areDomainsOnSameHost, hostFromDomain } from '../utils/domain.utils.js';\nimport type {\n\tGetSessionOptions,\n\tIntegrationAuthenticationProvider,\n\tIntegrationAuthenticationSessionDescriptor,\n} from './integrationAuthenticationProvider.js';\nimport type { ProviderAuthenticationSession, SessionPublication } from './models.js';\nimport { getSessionIdentity } from './models.js';\n\ntype Observation = {\n\trequest: number;\n\tidentity: string | undefined;\n\tdescriptorDomain: string;\n\tactualDomain: string;\n\tcloud: boolean | undefined;\n\tsessionKey?: string;\n\tsessionId?: string;\n\tconnectionId?: string;\n};\n\ntype Retirement = {\n\tdescriptors: Set<string>;\n\tactuals: Set<string>;\n\thost?: string;\n\tall?: boolean;\n};\n\nfunction domainKey(domain: string): string {\n\treturn hostFromDomain(domain) ?? domain;\n}\n\nfunction descriptorKey(domain: string, connectionId: string | undefined, cloud: boolean | undefined): string {\n\treturn JSON.stringify([domainKey(domain), connectionId, cloud]);\n}\n\nfunction actualKey(domain: string, id: string, cloud: boolean | undefined): string {\n\treturn JSON.stringify([domainKey(domain), id, cloud]);\n}\n\nexport class ObservedAuthenticationProvider implements IntegrationAuthenticationProvider {\n\tprivate readonly observations = new Map<string, Observation>();\n\tprivate readonly credentials = new Map<string, Observation>();\n\tprivate readonly descriptorRetirements = new Map<string, number>();\n\tprivate readonly actualRetirements = new Map<string, number>();\n\tprivate readonly hostRetirements = new Map<string, number>();\n\tprivate readonly activeRetirements = new Set<Retirement>();\n\tprivate sequence = 0;\n\tprivate globalRetirement = 0;\n\tprivate disposed = false;\n\n\tconstructor(\n\t\tprivate readonly host: IntegrationAuthenticationProvider,\n\t\tprivate readonly selfManaged: boolean,\n\t\tprivate readonly publish: (publication: SessionPublication, domains: (string | undefined)[]) => void,\n\t) {}\n\n\tget onDidChange(): Event<void> {\n\t\treturn this.host.onDidChange;\n\t}\n\n\tasync getSession(\n\t\tdescriptor: IntegrationAuthenticationSessionDescriptor,\n\t\toptions?: GetSessionOptions,\n\t): Promise<ProviderAuthenticationSession | undefined> {\n\t\tif (this.disposed) return undefined;\n\n\t\tconst request = ++this.sequence;\n\t\tconst scope = JSON.stringify([\n\t\t\tdescriptor.connectionId,\n\t\t\tdomainKey(descriptor.domain),\n\t\t\tdescriptor.cloud,\n\t\t\tdescriptor.scopes,\n\t\t]);\n\t\tconst source = await this.host.getSession(descriptor, options);\n\t\tif (source != null && this.selfManaged && !areDomainsOnSameHost(descriptor.domain, source.domain)) {\n\t\t\tthrow new CancellationError();\n\t\t}\n\t\tif (this.isRetired(request, descriptor, source)) throw new CancellationError();\n\n\t\tconst identity = getSessionIdentity(source);\n\t\tconst previous = this.observations.get(scope);\n\t\tconst sessionKey =\n\t\t\tsource == null\n\t\t\t\t? (previous?.sessionKey ??\n\t\t\t\t\t(descriptor.connectionId\n\t\t\t\t\t\t? actualKey(descriptor.domain, descriptor.connectionId, descriptor.cloud ?? true)\n\t\t\t\t\t\t: undefined))\n\t\t\t\t: actualKey(source.domain || descriptor.domain, source.id, source.cloud);\n\t\tconst credential = sessionKey == null ? undefined : this.credentials.get(sessionKey);\n\t\tconst latest =\n\t\t\tcredential != null && (previous == null || credential.request > previous.request) ? credential : previous;\n\t\tif (latest != null && latest.request > request && latest.identity !== identity) {\n\t\t\tthrow new CancellationError();\n\t\t}\n\n\t\tconst session: ProviderAuthenticationSession | undefined =\n\t\t\tsource == null\n\t\t\t\t? undefined\n\t\t\t\t: {\n\t\t\t\t\t\tid: source.id,\n\t\t\t\t\t\taccessToken: source.accessToken,\n\t\t\t\t\t\taccount: source.account,\n\t\t\t\t\t\tscopes: source.scopes,\n\t\t\t\t\t\tcloud: source.cloud,\n\t\t\t\t\t\ttype: source.type,\n\t\t\t\t\t\texpiresAt: source.expiresAt,\n\t\t\t\t\t\tdomain: source.domain,\n\t\t\t\t\t\tbaseUrl: source.baseUrl,\n\t\t\t\t\t\tprotocol: source.protocol,\n\t\t\t\t\t\tappKey: source.appKey,\n\t\t\t\t\t};\n\t\tif (latest == null || latest.request <= request) {\n\t\t\tif (previous == null || previous.identity !== identity || credential?.identity !== identity) {\n\t\t\t\tthis.publish(\n\t\t\t\t\t{\n\t\t\t\t\t\tsession: session,\n\t\t\t\t\t\tpreviousSessionId: latest?.sessionId ?? descriptor.connectionId,\n\t\t\t\t\t\tconnectionId: descriptor.connectionId,\n\t\t\t\t\t\tcloud: session != null ? session.cloud : (latest?.cloud ?? descriptor.cloud),\n\t\t\t\t\t\treplacePrimary: !descriptor.connectionId,\n\t\t\t\t\t},\n\t\t\t\t\t[descriptor.domain, session?.domain, previous?.actualDomain],\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst observation: Observation = {\n\t\t\t\trequest: request,\n\t\t\t\tidentity: identity,\n\t\t\t\tdescriptorDomain: descriptor.domain,\n\t\t\t\tactualDomain: session?.domain || descriptor.domain,\n\t\t\t\tcloud: session?.cloud ?? descriptor.cloud,\n\t\t\t\tsessionKey: sessionKey,\n\t\t\t\tsessionId: source?.id ?? latest?.sessionId ?? descriptor.connectionId,\n\t\t\t\tconnectionId: descriptor.connectionId,\n\t\t\t};\n\t\t\tthis.observations.set(scope, observation);\n\t\t\tif (sessionKey != null) {\n\t\t\t\tthis.credentials.set(sessionKey, observation);\n\t\t\t}\n\t\t}\n\n\t\treturn session;\n\t}\n\n\tasync deleteSession(\n\t\tdescriptor: IntegrationAuthenticationSessionDescriptor,\n\t\toptions?: { preserveConfigured?: boolean },\n\t): Promise<void> {\n\t\tconst retirement = this.retireConnection(descriptor);\n\t\tthis.activeRetirements.add(retirement);\n\t\ttry {\n\t\t\tawait this.host.deleteSession(descriptor, options);\n\t\t} finally {\n\t\t\tthis.markRetirement(retirement);\n\t\t\tthis.activeRetirements.delete(retirement);\n\t\t}\n\t}\n\n\tasync deleteAllSessions(descriptor?: IntegrationAuthenticationSessionDescriptor): Promise<void> {\n\t\tconst retirement = this.retireAll(this.selfManaged ? descriptor?.domain : undefined);\n\t\tthis.activeRetirements.add(retirement);\n\t\ttry {\n\t\t\tawait this.host.deleteAllSessions(descriptor);\n\t\t} finally {\n\t\t\tthis.markRetirement(retirement);\n\t\t\tthis.activeRetirements.delete(retirement);\n\t\t}\n\t}\n\n\tdispose(): void {\n\t\tif (this.disposed) return;\n\n\t\tthis.disposed = true;\n\t\tthis.retireAll();\n\t\tthis.host.dispose();\n\t}\n\n\tprivate isRetired(\n\t\trequest: number,\n\t\tdescriptor: IntegrationAuthenticationSessionDescriptor,\n\t\tsession: ProviderAuthenticationSession | undefined,\n\t): boolean {\n\t\tif (this.disposed || request < this.globalRetirement) return true;\n\n\t\tconst host = domainKey(descriptor.domain);\n\t\tconst variants = new Set([undefined, descriptor.cloud, session?.cloud]);\n\t\tif (descriptor.cloud == null && session?.cloud == null) {\n\t\t\tvariants.add(true);\n\t\t\tvariants.add(false);\n\t\t}\n\t\tconst descriptorIdentities = Array.from(variants, cloud =>\n\t\t\tdescriptorKey(descriptor.domain, descriptor.connectionId, cloud),\n\t\t);\n\t\tconst actual =\n\t\t\tsession == null ? undefined : actualKey(session.domain || descriptor.domain, session.id, session.cloud);\n\t\tconst actualAnyVariant =\n\t\t\tsession == null ? undefined : actualKey(session.domain || descriptor.domain, session.id, undefined);\n\t\tif (\n\t\t\trequest < (this.hostRetirements.get(host) ?? 0) ||\n\t\t\tdescriptorIdentities.some(key => request < (this.descriptorRetirements.get(key) ?? 0)) ||\n\t\t\t(actual != null && request < (this.actualRetirements.get(actual) ?? 0)) ||\n\t\t\t(actualAnyVariant != null && request < (this.actualRetirements.get(actualAnyVariant) ?? 0))\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\n\t\tfor (const retirement of this.activeRetirements) {\n\t\t\tif (\n\t\t\t\tretirement.all ||\n\t\t\t\tretirement.host === host ||\n\t\t\t\tdescriptorIdentities.some(key => retirement.descriptors.has(key)) ||\n\t\t\t\t(actual != null && retirement.actuals.has(actual)) ||\n\t\t\t\t(actualAnyVariant != null && retirement.actuals.has(actualAnyVariant))\n\t\t\t) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tprivate retireConnection(descriptor: IntegrationAuthenticationSessionDescriptor): Retirement {\n\t\tconst host = domainKey(descriptor.domain);\n\t\tconst matching = [...this.observations.values()].filter(o => {\n\t\t\tif (domainKey(o.descriptorDomain) !== host && domainKey(o.actualDomain) !== host) return false;\n\t\t\tif (descriptor.cloud != null && o.cloud !== descriptor.cloud) return false;\n\t\t\treturn descriptor.connectionId == null\n\t\t\t\t? o.connectionId == null\n\t\t\t\t: o.connectionId === descriptor.connectionId || o.sessionId === descriptor.connectionId;\n\t\t});\n\t\tconst actuals = new Set(\n\t\t\tmatching\n\t\t\t\t.filter((o): o is Observation & { sessionId: string } => o.sessionId != null)\n\t\t\t\t.map(o => actualKey(o.actualDomain, o.sessionId, o.cloud)),\n\t\t);\n\t\tif (descriptor.connectionId != null) {\n\t\t\tactuals.add(actualKey(descriptor.domain, descriptor.connectionId, descriptor.cloud));\n\t\t}\n\n\t\tconst targets = [...this.observations.values()].filter(o => {\n\t\t\tif (descriptor.cloud != null && o.cloud !== descriptor.cloud) return false;\n\t\t\treturn (\n\t\t\t\tmatching.includes(o) ||\n\t\t\t\t(o.sessionId != null && actuals.has(actualKey(o.actualDomain, o.sessionId, o.cloud)))\n\t\t\t);\n\t\t});\n\t\tconst retirement: Retirement = { descriptors: new Set(), actuals: new Set() };\n\t\tretirement.descriptors.add(descriptorKey(descriptor.domain, descriptor.connectionId, descriptor.cloud));\n\t\tif (descriptor.connectionId != null) {\n\t\t\tretirement.actuals.add(actualKey(descriptor.domain, descriptor.connectionId, descriptor.cloud));\n\t\t}\n\n\t\tfor (const target of targets) {\n\t\t\tthis.addTarget(retirement, target);\n\t\t\tthis.publish(\n\t\t\t\t{\n\t\t\t\t\tpreviousSessionId: target.sessionId,\n\t\t\t\t\tconnectionId: target.connectionId,\n\t\t\t\t\tcloud: target.cloud,\n\t\t\t\t\treplacePrimary: target.connectionId == null,\n\t\t\t\t},\n\t\t\t\t[target.descriptorDomain, target.actualDomain],\n\t\t\t);\n\t\t}\n\n\t\tif (targets.every(target => target.connectionId !== descriptor.connectionId)) {\n\t\t\tthis.publish(\n\t\t\t\t{\n\t\t\t\t\tpreviousSessionId: descriptor.connectionId,\n\t\t\t\t\tconnectionId: descriptor.connectionId,\n\t\t\t\t\tcloud: descriptor.cloud,\n\t\t\t\t\treplacePrimary: descriptor.connectionId == null,\n\t\t\t\t},\n\t\t\t\t[descriptor.domain],\n\t\t\t);\n\t\t}\n\n\t\tthis.removeTargets(targets);\n\t\tthis.markRetirement(retirement);\n\t\treturn retirement;\n\t}\n\n\tprivate retireAll(domain?: string): Retirement {\n\t\tconst host = domain == null ? undefined : domainKey(domain);\n\t\tconst retirement: Retirement = { descriptors: new Set(), actuals: new Set(), host: host, all: host == null };\n\t\tconst targets = [...this.observations.values()].filter(\n\t\t\to => host == null || domainKey(o.descriptorDomain) === host || domainKey(o.actualDomain) === host,\n\t\t);\n\t\tfor (const target of targets) {\n\t\t\tthis.addTarget(retirement, target);\n\t\t\tthis.publish(\n\t\t\t\t{\n\t\t\t\t\tpreviousSessionId: target.sessionId,\n\t\t\t\t\tconnectionId: target.connectionId,\n\t\t\t\t\tcloud: target.cloud,\n\t\t\t\t\treplacePrimary: target.connectionId == null,\n\t\t\t\t},\n\t\t\t\t[target.descriptorDomain, target.actualDomain],\n\t\t\t);\n\t\t}\n\n\t\tif (targets.length === 0) {\n\t\t\tthis.publish({ replacePrimary: true }, [domain]);\n\t\t}\n\n\t\tthis.removeTargets(targets);\n\t\tthis.markRetirement(retirement);\n\t\treturn retirement;\n\t}\n\n\tprivate addTarget(retirement: Retirement, observation: Observation): void {\n\t\tretirement.descriptors.add(\n\t\t\tdescriptorKey(observation.descriptorDomain, observation.connectionId, observation.cloud),\n\t\t);\n\t\tif (observation.sessionId != null) {\n\t\t\tretirement.actuals.add(actualKey(observation.actualDomain, observation.sessionId, observation.cloud));\n\t\t}\n\t}\n\n\tprivate removeTargets(targets: Observation[]): void {\n\t\tconst removed = new Set(targets);\n\t\tfor (const [key, observation] of this.observations) {\n\t\t\tif (removed.has(observation)) {\n\t\t\t\tthis.observations.delete(key);\n\t\t\t}\n\t\t}\n\n\t\tfor (const [key, observation] of this.credentials) {\n\t\t\tif (removed.has(observation)) {\n\t\t\t\tthis.credentials.delete(key);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate markRetirement(retirement: Retirement): void {\n\t\tconst mark = ++this.sequence;\n\t\tif (retirement.all) {\n\t\t\tthis.globalRetirement = mark;\n\t\t}\n\t\tif (retirement.host != null) {\n\t\t\tthis.hostRetirements.set(retirement.host, mark);\n\t\t}\n\t\tfor (const key of retirement.descriptors) {\n\t\t\tthis.descriptorRetirements.set(key, mark);\n\t\t}\n\n\t\tfor (const key of retirement.actuals) {\n\t\t\tthis.actualRetirements.set(key, mark);\n\t\t}\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { CacheController } from "../../utils/promiseCache.js";
|
|
2
|
+
import { Autolink, AutolinkReference, DynamicAutolinkReference, RefSet } from "../../git/models/autolink.js";
|
|
3
|
+
import { ProviderReference } from "../../git/models/remoteProvider.js";
|
|
2
4
|
import { IssueProjection, IssueSearchCapabilities, IssueSearchCriteria, IssueSearchRelationship, IssueStateFilter } from "../../git/models/issue.js";
|
|
3
5
|
import { PullRequestFilter, PullRequestProjection, PullRequestSearchCapabilities, PullRequestSearchCriteria, PullRequestStateFilter } from "../../git/models/pullRequest.js";
|
|
4
6
|
import { Account } from "../../git/models/author.js";
|
|
@@ -14,7 +16,7 @@ import { CurrentAccountResult } from "./reads/currentAccount.js";
|
|
|
14
16
|
import { IssueBatchResult, IssueBatchTarget } from "./reads/issueBatch.js";
|
|
15
17
|
import { PullRequestBatchResult, PullRequestBatchTarget } from "./reads/pullRequestBatch.js";
|
|
16
18
|
import { PullRequestBranchResult, PullRequestBranchTarget } from "./reads/pullRequestBranches.js";
|
|
17
|
-
import { ClosedPullRequestSweepOptions, IntegrationManager, ListOrgsOptions, ListProjectsOptions, ProviderBroadenOrg, ProviderRepositoriesInput, ProviderRepositoryInput, ProviderSweepTarget, ProviderSweepTargetEvent, PullRequestSweepOptions } from "./manager.js";
|
|
19
|
+
import { ClosedPullRequestSweepOptions, GetAutolinkReferencesOptions, IntegrationManager, ListOrgsOptions, ListProjectsOptions, ProviderBroadenOrg, ProviderRepositoriesInput, ProviderRepositoryInput, ProviderSweepTarget, ProviderSweepTargetEvent, PullRequestSweepOptions } from "./manager.js";
|
|
18
20
|
import { IntegrationAuthenticationProvider, IntegrationAuthenticationProviderDescriptor, IntegrationAuthenticationSessionDescriptor } from "./authentication/integrationAuthenticationProvider.js";
|
|
19
21
|
import { AccountProvider, AuthenticationSessionsChangeEvent, ConfigChangeEvent, ConfigProvider, HttpProvider, IntegrationServiceHooks, IntegrationStorageProvider, IntegrationsRemoteConfig, RepositoriesProvider } from "./context.js";
|
|
20
22
|
import { ManualTokenAuthProviderOptions, createManualTokenAuthProvider } from "./authentication/manualTokenProvider.js";
|
|
@@ -78,5 +80,5 @@ export interface IntegrationManagerContext {
|
|
|
78
80
|
*/
|
|
79
81
|
export declare function createIntegrationManager(ctx: IntegrationManagerContext): IntegrationManager;
|
|
80
82
|
//#endregion
|
|
81
|
-
export { type Account, type AccountProvider, type AuthenticationSessionLike, type AuthenticationSessionsChangeEvent, type ClosedPullRequestSweepOptions, type CloudIntegrationAuthType, type CloudIntegrationConnection, type CloudIntegrationType, type ConfigChangeEvent, type ConfigProvider, type ConfiguredIntegrationDescriptor, type ConfiguredIntegrationsChangeEvent, type ConnectionStateChangeEvent, type CurrentAccountResult, type FieldPresence, GitCloudHostIntegrationId, GitSelfManagedHostIntegrationId, type HttpProvider, type IntegrationAuthenticationProvider, type IntegrationAuthenticationProviderDescriptor, type IntegrationAuthenticationSessionDescriptor, type IntegrationIds, type IntegrationManager, type IntegrationServiceHooks, type IntegrationStorageProvider, type IntegrationsRemoteConfig, type IssueBatchResult, type IssueBatchTarget, type IssueCountResult, type IssueCountScope, type IssueEtagInclude, type IssueFieldGroup, IssueFilter, type IssueProjection, type IssueSearchCapabilities, type IssueSearchCriteria, type IssueSearchRelationship, type IssueStateFilter, IssuesCloudHostIntegrationId, IssuesSelfManagedHostIntegrationId, type ListOrgsOptions, type ListProjectsOptions, type ManualTokenAuthProviderOptions, type ProviderAuthenticationSession, type ProviderBroadenOrg, type ProviderBroadenResult, type ProviderOrganization, type ProviderPageInfo, type ProviderPagedResult, type ProviderRepositoriesInput, type ProviderRepositoryInput, type ProviderRepositoryShape, type ProviderResult, type ProviderSweepResult, type ProviderSweepTarget, type ProviderSweepTargetEvent, type ProviderWarning, type ProviderWarningCause, type ProviderWarningCauseReason, type ProviderWarningKind, type ProviderWarningOmission, type ProviderWarningOmissionKind, type ProviderWarningOmissionRecovery, type ProviderWarningOmissionScope, type ProviderWarningScope, type ProviderWarningSelector, type ProviderWarningUnreadableItems, type PullRequestBatchResult, type PullRequestBatchTarget, type PullRequestBranchResult, type PullRequestBranchTarget, type PullRequestCountResult, type PullRequestCountScope, type PullRequestEtagInclude, type PullRequestFieldGroup, PullRequestFilter, type PullRequestProjection, type PullRequestSearchCapabilities, type PullRequestSearchCriteria, type PullRequestStateFilter, type PullRequestSweepOptions, type RepositoriesProvider, type RepositoryIdentity, type RepositoryResolution, type RepositoryResolutionStatus, type ResolveRepositoryResult, type Source, type Sources, type SupportedCloudIntegrationIds, areDomainsOnSameHost, createManualTokenAuthProvider, getIssueFieldPresence, getPullRequestFieldPresence, hostFromDomain, isIntegrationId, isSupportedCloudIntegrationId, toCloudIntegrationType, toIntegrationId };
|
|
83
|
+
export { type Account, type AccountProvider, type AuthenticationSessionLike, type AuthenticationSessionsChangeEvent, type Autolink, type AutolinkReference, type ClosedPullRequestSweepOptions, type CloudIntegrationAuthType, type CloudIntegrationConnection, type CloudIntegrationType, type ConfigChangeEvent, type ConfigProvider, type ConfiguredIntegrationDescriptor, type ConfiguredIntegrationsChangeEvent, type ConnectionStateChangeEvent, type CurrentAccountResult, type DynamicAutolinkReference, type FieldPresence, type GetAutolinkReferencesOptions, GitCloudHostIntegrationId, GitSelfManagedHostIntegrationId, type HttpProvider, type IntegrationAuthenticationProvider, type IntegrationAuthenticationProviderDescriptor, type IntegrationAuthenticationSessionDescriptor, type IntegrationIds, type IntegrationManager, type IntegrationServiceHooks, type IntegrationStorageProvider, type IntegrationsRemoteConfig, type IssueBatchResult, type IssueBatchTarget, type IssueCountResult, type IssueCountScope, type IssueEtagInclude, type IssueFieldGroup, IssueFilter, type IssueProjection, type IssueSearchCapabilities, type IssueSearchCriteria, type IssueSearchRelationship, type IssueStateFilter, IssuesCloudHostIntegrationId, IssuesSelfManagedHostIntegrationId, type ListOrgsOptions, type ListProjectsOptions, type ManualTokenAuthProviderOptions, type ProviderAuthenticationSession, type ProviderBroadenOrg, type ProviderBroadenResult, type ProviderOrganization, type ProviderPageInfo, type ProviderPagedResult, type ProviderReference, type ProviderRepositoriesInput, type ProviderRepositoryInput, type ProviderRepositoryShape, type ProviderResult, type ProviderSweepResult, type ProviderSweepTarget, type ProviderSweepTargetEvent, type ProviderWarning, type ProviderWarningCause, type ProviderWarningCauseReason, type ProviderWarningKind, type ProviderWarningOmission, type ProviderWarningOmissionKind, type ProviderWarningOmissionRecovery, type ProviderWarningOmissionScope, type ProviderWarningScope, type ProviderWarningSelector, type ProviderWarningUnreadableItems, type PullRequestBatchResult, type PullRequestBatchTarget, type PullRequestBranchResult, type PullRequestBranchTarget, type PullRequestCountResult, type PullRequestCountScope, type PullRequestEtagInclude, type PullRequestFieldGroup, PullRequestFilter, type PullRequestProjection, type PullRequestSearchCapabilities, type PullRequestSearchCriteria, type PullRequestStateFilter, type PullRequestSweepOptions, type RefSet, type RepositoriesProvider, type RepositoryIdentity, type RepositoryResolution, type RepositoryResolutionStatus, type ResolveRepositoryResult, type Source, type Sources, type SupportedCloudIntegrationIds, areDomainsOnSameHost, createManualTokenAuthProvider, getIssueFieldPresence, getPullRequestFieldPresence, hostFromDomain, isIntegrationId, isSupportedCloudIntegrationId, toCloudIntegrationType, toIntegrationId };
|
|
82
84
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../../plus/integrations/src/index.ts"],"sourcesContent":["// Public facade for `@gitlens/integrations`.\n//\n// External consumers should import from this entry point only, not from the\n// package's internal subpaths, with one exception: the lightweight, token-scoped\n// read API is a supported public subpath (`./lite.js`). It's kept out of this\n// facade on purpose so importing the session-managed manager doesn't eagerly pull\n// in every provider API client. The internal classes (IntegrationService,\n// IntegrationAuthenticationService, etc.) are not part of the public API and\n// may be refactored without semver bumps.\n\nimport type { Account } from '@gitlens/git/models/author.js';\nimport { CacheController } from '@gitlens/utils/promiseCache.js';\nimport type { IntegrationIds } from './constants.js';\nimport type {\n\tAccountProvider,\n\tConfigProvider,\n\tHttpProvider,\n\tIntegrationCacheProvider,\n\tIntegrationServiceHooks,\n\tIntegrationStorageProvider,\n\tRepositoriesProvider,\n} from './context.js';\nimport { createIntegrationService } from './integrationService.js';\nimport type { IntegrationManager } from './manager.js';\n\n/** A cached provider value, which may still be resolving. */\nexport type IntegrationManagerCacheResult<T> = Promise<T | undefined> | T | undefined;\n\n/** Produces an account value on a cache miss. */\nexport type IntegrationManagerCacheLoader<T> = (cacheable: CacheController) => {\n\tvalue: IntegrationManagerCacheResult<T>;\n\texpiresAt?: number;\n};\n\n/** Stable integration identity supplied to the consumer-owned account cache. */\nexport interface IntegrationAccountCacheDescriptor {\n\treadonly id: IntegrationIds;\n\treadonly domain?: string;\n}\n\n/** Cache controls attached to a provider account lookup. */\nexport interface IntegrationManagerCacheOptions {\n\treadonly connectionId?: string;\n\treadonly etag?: string;\n\treadonly expiryOverride?: boolean | number;\n\treadonly expireOnError?: boolean;\n}\n\n/**\n * Optional consumer-owned cache for values reused by the public manager facade.\n *\n * The manager only needs cross-call caching for provider identity lookups. Other caches used by the GitLens\n * extension host are implementation details and deliberately stay out of this contract.\n */\nexport interface IntegrationManagerCacheProvider {\n\tgetCurrentAccount(\n\t\tintegration: IntegrationAccountCacheDescriptor,\n\t\tcacheable: IntegrationManagerCacheLoader<Account>,\n\t\toptions?: IntegrationManagerCacheOptions,\n\t): IntegrationManagerCacheResult<Account>;\n}\n\nfunction loadUncached<T>(loader: IntegrationManagerCacheLoader<T>): IntegrationManagerCacheResult<T> {\n\treturn loader(new CacheController()).value;\n}\n\nconst uncachedIntegrationCacheProvider: IntegrationCacheProvider = {\n\tgetRepositoryMetadata: (_repo, _integration, loader) => loadUncached(loader),\n\tgetRepositoryDefaultBranch: (_repo, _integration, loader) => loadUncached(loader),\n\tgetPullRequestForSha: (_sha, _repo, _integration, loader) => loadUncached(loader),\n\tgetPullRequestForBranch: (_branch, _repo, _integration, loader) => loadUncached(loader),\n\tgetPullRequest: (_id, _resource, _integration, loader) => loadUncached(loader),\n\tgetIssueOrPullRequest: (_id, _type, _resource, _integration, loader) => loadUncached(loader),\n\tgetIssue: (_id, _resource, _integration, loader) => loadUncached(loader),\n\tgetCurrentAccount: (_integration, loader) => loadUncached(loader),\n\t// Nothing is cached, so there is nothing to evict.\n\tdeletePullRequests: () => {},\n};\n\nfunction toIntegrationCacheProvider(cache: IntegrationManagerCacheProvider | undefined): IntegrationCacheProvider {\n\tif (cache == null) return uncachedIntegrationCacheProvider;\n\n\treturn {\n\t\t...uncachedIntegrationCacheProvider,\n\t\tgetCurrentAccount: (integration, loader, options) =>\n\t\t\tcache.getCurrentAccount({ id: integration.id, domain: integration.domain }, loader, options),\n\t};\n}\n\n/**\n * Consumer-facing runtime for {@link createIntegrationManager}.\n *\n * External consumers may omit `cache`; reads then execute their loaders directly without cross-call caching.\n * The extension host's broader integration context remains private to the implementation.\n */\nexport interface IntegrationManagerContext {\n\treadonly storage: IntegrationStorageProvider;\n\treadonly account: AccountProvider;\n\treadonly config: ConfigProvider;\n\treadonly http: HttpProvider;\n\treadonly cache?: IntegrationManagerCacheProvider;\n\treadonly repositories: RepositoriesProvider;\n\treadonly hooks?: IntegrationServiceHooks;\n}\n\nexport type {\n\tClosedPullRequestSweepOptions,\n\tIntegrationManager,\n\tListOrgsOptions,\n\tListProjectsOptions,\n\t// Every option shape a caller has to BUILD is exported, not just the ones the manager returns:\n\t// `manager.js` is not a public subpath, so a type omitted here can't be named by a consumer at all\n\t// (`broadenIssues`' `orgs` needed `ProviderBroadenOrg` and had to be re-declared downstream).\n\tProviderBroadenOrg,\n\tProviderRepositoriesInput,\n\tProviderRepositoryInput,\n\tProviderSweepTarget,\n\tProviderSweepTargetEvent,\n\tPullRequestSweepOptions,\n} from './manager.js';\n\n/**\n * Construct an `@gitlens/integrations` manager bound to the supplied runtime.\n *\n * The runtime is the **single** cross-boundary contract — anything the\n * package needs (HTTP, storage, cache, auth, subscription, telemetry, UI,\n * configuration, environment) flows through it. The package never imports\n * `vscode`, `Container`, or any consumer-internal types.\n *\n * The returned manager owns its internal services; dispose it (or its\n * containing scope) to release every cached integration plus the runtime's\n * own VS Code subscriptions.\n */\nexport function createIntegrationManager(ctx: IntegrationManagerContext): IntegrationManager {\n\treturn createIntegrationService({\n\t\t...ctx,\n\t\tcache: toIntegrationCacheProvider(ctx.cache),\n\t});\n}\n\n// Re-exports for the public API surface.\nexport type {\n\tAccountProvider,\n\tAuthenticationSessionsChangeEvent,\n\tConfigChangeEvent,\n\tConfigProvider,\n\tRepositoriesProvider,\n\tHttpProvider,\n\tIntegrationsRemoteConfig,\n\tIntegrationServiceHooks,\n\tIntegrationStorageProvider,\n} from './context.js';\nexport type { Source, Sources } from './telemetry.js';\nexport type { IntegrationIds, SupportedCloudIntegrationIds } from './constants.js';\nexport type { ConfiguredIntegrationsChangeEvent } from './authentication/configuredIntegrationService.js';\n\n// Authentication contract — what `IntegrationServiceHooks.createAuthenticationProvider`\n// implementers return. Consumers can plug in any auth strategy (manual token,\n// OAuth, host-managed) by returning an object implementing this interface from\n// the hook.\nexport type {\n\tIntegrationAuthenticationProvider,\n\tIntegrationAuthenticationProviderDescriptor,\n\tIntegrationAuthenticationSessionDescriptor,\n} from './authentication/integrationAuthenticationProvider.js';\nexport type {\n\tAuthenticationSessionLike,\n\tCloudIntegrationAuthType,\n\tCloudIntegrationConnection,\n\tCloudIntegrationType,\n\tConfiguredIntegrationDescriptor,\n\tProviderAuthenticationSession,\n} from './authentication/models.js';\n// Provider-id mapping helpers for consumers bridging their own provider ids to `IntegrationIds`\n// (e.g. mapping multi-account connections from `getConfigured` back to a provider) and vice versa.\nexport { toCloudIntegrationType, toIntegrationId } from './authentication/models.js';\n// Domain normalization is part of connection selection and repository resolution; consumers should use the\n// same implementation rather than importing an internal utility subpath or maintaining a divergent copy.\nexport { areDomainsOnSameHost, hostFromDomain } from './utils/domain.utils.js';\n\n// Convenience: wrap a static access token (env var, CLI flag, secret manager)\n// as an `IntegrationAuthenticationProvider`. For OAuth/refresh flows, implement\n// the interface directly — this helper is for non-interactive consumers only.\nexport {\n\tcreateManualTokenAuthProvider,\n\ttype ManualTokenAuthProviderOptions,\n} from './authentication/manualTokenProvider.js';\n\nexport {\n\tGitCloudHostIntegrationId,\n\tGitSelfManagedHostIntegrationId,\n\tIssuesCloudHostIntegrationId,\n\tIssuesSelfManagedHostIntegrationId,\n\tisIntegrationId,\n\tisSupportedCloudIntegrationId,\n} from './constants.js';\n\n// Neutral pagination + warning result types the Kepler ProviderBackend adapter maps to its own DTOs.\n// These carry no `@gitkraken/provider-apis` types, so consumers depend only on `@gitkraken/core-gitlens`.\nexport type {\n\tConnectionStateChangeEvent,\n\tProviderBroadenResult,\n\tProviderPagedResult,\n\tProviderPageInfo,\n\tProviderResult,\n\tProviderSweepResult,\n\tProviderWarning,\n\tProviderWarningCause,\n\tProviderWarningCauseReason,\n\tProviderWarningKind,\n\tProviderWarningOmission,\n\tProviderWarningOmissionKind,\n\tProviderWarningOmissionRecovery,\n\tProviderWarningOmissionScope,\n\tProviderWarningScope,\n\tProviderWarningSelector,\n\tProviderWarningUnreadableItems,\n\tProviderOrganization,\n\tProviderRepositoryShape,\n\tRepositoryIdentity,\n\tRepositoryResolution,\n\tRepositoryResolutionStatus,\n\tResolveRepositoryResult,\n} from './results.js';\n// Runtime enums — re-exported as values (not `export type`) so consumers can read their members.\nexport { IssueFilter, PullRequestFilter } from './providerFilters.js';\n// The filtered issue search's criteria model and the capability table that says which of it a provider honors.\n// String unions and plain interfaces, so a consumer builds criteria without importing an internal subpath.\nexport type { IssueSearchCapabilities, IssueSearchCriteria, IssueSearchRelationship } from './providerFilters.js';\n// Account-wide pull-request search criteria and the per-provider capability table.\nexport type { PullRequestSearchCapabilities, PullRequestSearchCriteria } from './providerFilters.js';\n// The count-only issue and pull-request probes' input and result shapes.\nexport type {\n\tIssueCountResult,\n\tIssueCountScope,\n\tPullRequestCountResult,\n\tPullRequestCountScope,\n} from './reads/counts.js';\nexport type { IssueBatchResult, IssueBatchTarget } from './reads/issueBatch.js';\nexport type { PullRequestBatchResult, PullRequestBatchTarget } from './reads/pullRequestBatch.js';\nexport type { IssueEtagInclude, PullRequestEtagInclude } from './models/integration.js';\nexport type { PullRequestBranchResult, PullRequestBranchTarget } from './reads/pullRequestBranches.js';\n// The current-account read's result, and the account shape every identity-bearing read already returns.\nexport type { CurrentAccountResult } from './reads/currentAccount.js';\nexport type { Account } from '@gitlens/git/models/author.js';\n// Cross-provider PR/issue state filters (string unions in the git models).\nexport type { PullRequestStateFilter } from '@gitlens/git/models/pullRequest.js';\nexport type { IssueStateFilter } from '@gitlens/git/models/issue.js';\n// Which read produced a row, and which of its fields that read fetched.\nexport type { PullRequestProjection } from '@gitlens/git/models/pullRequest.js';\nexport type { IssueProjection } from '@gitlens/git/models/issue.js';\nexport type { FieldPresence, IssueFieldGroup, PullRequestFieldGroup } from './fieldPresence.js';\nexport { getIssueFieldPresence, getPullRequestFieldPresence } from './fieldPresence.js';\n"],"mappings":";;;;;;;;;;AA8DA,SAAS,aAAgB,QAA4E;CACpG,OAAO,OAAO,IAAI,gBAAgB,CAAC,CAAC,CAAC;AACtC;AAEA,MAAM,mCAA6D;CAClE,wBAAwB,OAAO,cAAc,WAAW,aAAa,MAAM;CAC3E,6BAA6B,OAAO,cAAc,WAAW,aAAa,MAAM;CAChF,uBAAuB,MAAM,OAAO,cAAc,WAAW,aAAa,MAAM;CAChF,0BAA0B,SAAS,OAAO,cAAc,WAAW,aAAa,MAAM;CACtF,iBAAiB,KAAK,WAAW,cAAc,WAAW,aAAa,MAAM;CAC7E,wBAAwB,KAAK,OAAO,WAAW,cAAc,WAAW,aAAa,MAAM;CAC3F,WAAW,KAAK,WAAW,cAAc,WAAW,aAAa,MAAM;CACvE,oBAAoB,cAAc,WAAW,aAAa,MAAM;CAEhE,0BAA0B,CAAC;AAC5B;AAEA,SAAS,2BAA2B,OAA8E;CACjH,IAAI,SAAS,MAAM,OAAO;CAE1B,OAAO;EACN,GAAG;EACH,oBAAoB,aAAa,QAAQ,YACxC,MAAM,kBAAkB;GAAE,IAAI,YAAY;GAAI,QAAQ,YAAY;EAAO,GAAG,QAAQ,OAAO;CAC7F;AACD;;;;;;;;;;;;;AA8CA,SAAgB,yBAAyB,KAAoD;CAC5F,OAAO,yBAAyB;EAC/B,GAAG;EACH,OAAO,2BAA2B,IAAI,KAAK;CAC5C,CAAC;AACF"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../../plus/integrations/src/index.ts"],"sourcesContent":["// Public facade for `@gitlens/integrations`.\n//\n// External consumers should import from this entry point only, not from the\n// package's internal subpaths, with one exception: the lightweight, token-scoped\n// read API is a supported public subpath (`./lite.js`). It's kept out of this\n// facade on purpose so importing the session-managed manager doesn't eagerly pull\n// in every provider API client. The internal classes (IntegrationService,\n// IntegrationAuthenticationService, etc.) are not part of the public API and\n// may be refactored without semver bumps.\n\nimport type { Account } from '@gitlens/git/models/author.js';\nimport { CacheController } from '@gitlens/utils/promiseCache.js';\nimport type { IntegrationIds } from './constants.js';\nimport type {\n\tAccountProvider,\n\tConfigProvider,\n\tHttpProvider,\n\tIntegrationCacheProvider,\n\tIntegrationServiceHooks,\n\tIntegrationStorageProvider,\n\tRepositoriesProvider,\n} from './context.js';\nimport { createIntegrationService } from './integrationService.js';\nimport type { IntegrationManager } from './manager.js';\n\nexport type { Autolink, AutolinkReference, DynamicAutolinkReference, RefSet } from '@gitlens/git/models/autolink.js';\nexport type { ProviderReference } from '@gitlens/git/models/remoteProvider.js';\n\n/** A cached provider value, which may still be resolving. */\nexport type IntegrationManagerCacheResult<T> = Promise<T | undefined> | T | undefined;\n\n/** Produces an account value on a cache miss. */\nexport type IntegrationManagerCacheLoader<T> = (cacheable: CacheController) => {\n\tvalue: IntegrationManagerCacheResult<T>;\n\texpiresAt?: number;\n};\n\n/** Stable integration identity supplied to the consumer-owned account cache. */\nexport interface IntegrationAccountCacheDescriptor {\n\treadonly id: IntegrationIds;\n\treadonly domain?: string;\n}\n\n/** Cache controls attached to a provider account lookup. */\nexport interface IntegrationManagerCacheOptions {\n\treadonly connectionId?: string;\n\treadonly etag?: string;\n\treadonly expiryOverride?: boolean | number;\n\treadonly expireOnError?: boolean;\n}\n\n/**\n * Optional consumer-owned cache for values reused by the public manager facade.\n *\n * The manager only needs cross-call caching for provider identity lookups. Other caches used by the GitLens\n * extension host are implementation details and deliberately stay out of this contract.\n */\nexport interface IntegrationManagerCacheProvider {\n\tgetCurrentAccount(\n\t\tintegration: IntegrationAccountCacheDescriptor,\n\t\tcacheable: IntegrationManagerCacheLoader<Account>,\n\t\toptions?: IntegrationManagerCacheOptions,\n\t): IntegrationManagerCacheResult<Account>;\n}\n\nfunction loadUncached<T>(loader: IntegrationManagerCacheLoader<T>): IntegrationManagerCacheResult<T> {\n\treturn loader(new CacheController()).value;\n}\n\nconst uncachedIntegrationCacheProvider: IntegrationCacheProvider = {\n\tgetRepositoryMetadata: (_repo, _integration, loader) => loadUncached(loader),\n\tgetRepositoryDefaultBranch: (_repo, _integration, loader) => loadUncached(loader),\n\tgetPullRequestForSha: (_sha, _repo, _integration, loader) => loadUncached(loader),\n\tgetPullRequestForBranch: (_branch, _repo, _integration, loader) => loadUncached(loader),\n\tgetPullRequest: (_id, _resource, _integration, loader) => loadUncached(loader),\n\tgetIssueOrPullRequest: (_id, _type, _resource, _integration, loader) => loadUncached(loader),\n\tgetIssue: (_id, _resource, _integration, loader) => loadUncached(loader),\n\tgetCurrentAccount: (_integration, loader) => loadUncached(loader),\n\t// Nothing is cached, so there is nothing to evict.\n\tdeletePullRequests: () => {},\n};\n\nfunction toIntegrationCacheProvider(cache: IntegrationManagerCacheProvider | undefined): IntegrationCacheProvider {\n\tif (cache == null) return uncachedIntegrationCacheProvider;\n\n\treturn {\n\t\t...uncachedIntegrationCacheProvider,\n\t\tgetCurrentAccount: (integration, loader, options) =>\n\t\t\tcache.getCurrentAccount({ id: integration.id, domain: integration.domain }, loader, options),\n\t};\n}\n\n/**\n * Consumer-facing runtime for {@link createIntegrationManager}.\n *\n * External consumers may omit `cache`; reads then execute their loaders directly without cross-call caching.\n * The extension host's broader integration context remains private to the implementation.\n */\nexport interface IntegrationManagerContext {\n\treadonly storage: IntegrationStorageProvider;\n\treadonly account: AccountProvider;\n\treadonly config: ConfigProvider;\n\treadonly http: HttpProvider;\n\treadonly cache?: IntegrationManagerCacheProvider;\n\treadonly repositories: RepositoriesProvider;\n\treadonly hooks?: IntegrationServiceHooks;\n}\n\nexport type {\n\tClosedPullRequestSweepOptions,\n\tGetAutolinkReferencesOptions,\n\tIntegrationManager,\n\tListOrgsOptions,\n\tListProjectsOptions,\n\t// Every option shape a caller has to BUILD is exported, not just the ones the manager returns:\n\t// `manager.js` is not a public subpath, so a type omitted here can't be named by a consumer at all\n\t// (`broadenIssues`' `orgs` needed `ProviderBroadenOrg` and had to be re-declared downstream).\n\tProviderBroadenOrg,\n\tProviderRepositoriesInput,\n\tProviderRepositoryInput,\n\tProviderSweepTarget,\n\tProviderSweepTargetEvent,\n\tPullRequestSweepOptions,\n} from './manager.js';\n\n/**\n * Construct an `@gitlens/integrations` manager bound to the supplied runtime.\n *\n * The runtime is the **single** cross-boundary contract — anything the\n * package needs (HTTP, storage, cache, auth, subscription, telemetry, UI,\n * configuration, environment) flows through it. The package never imports\n * `vscode`, `Container`, or any consumer-internal types.\n *\n * The returned manager owns its internal services; dispose it (or its\n * containing scope) to release every cached integration plus the runtime's\n * own VS Code subscriptions.\n */\nexport function createIntegrationManager(ctx: IntegrationManagerContext): IntegrationManager {\n\treturn createIntegrationService({\n\t\t...ctx,\n\t\tcache: toIntegrationCacheProvider(ctx.cache),\n\t});\n}\n\n// Re-exports for the public API surface.\nexport type {\n\tAccountProvider,\n\tAuthenticationSessionsChangeEvent,\n\tConfigChangeEvent,\n\tConfigProvider,\n\tRepositoriesProvider,\n\tHttpProvider,\n\tIntegrationsRemoteConfig,\n\tIntegrationServiceHooks,\n\tIntegrationStorageProvider,\n} from './context.js';\nexport type { Source, Sources } from './telemetry.js';\nexport type { IntegrationIds, SupportedCloudIntegrationIds } from './constants.js';\nexport type { ConfiguredIntegrationsChangeEvent } from './authentication/configuredIntegrationService.js';\n\n// Authentication contract — what `IntegrationServiceHooks.createAuthenticationProvider`\n// implementers return. Consumers can plug in any auth strategy (manual token,\n// OAuth, host-managed) by returning an object implementing this interface from\n// the hook.\nexport type {\n\tIntegrationAuthenticationProvider,\n\tIntegrationAuthenticationProviderDescriptor,\n\tIntegrationAuthenticationSessionDescriptor,\n} from './authentication/integrationAuthenticationProvider.js';\nexport type {\n\tAuthenticationSessionLike,\n\tCloudIntegrationAuthType,\n\tCloudIntegrationConnection,\n\tCloudIntegrationType,\n\tConfiguredIntegrationDescriptor,\n\tProviderAuthenticationSession,\n} from './authentication/models.js';\n// Provider-id mapping helpers for consumers bridging their own provider ids to `IntegrationIds`\n// (e.g. mapping multi-account connections from `getConfigured` back to a provider) and vice versa.\nexport { toCloudIntegrationType, toIntegrationId } from './authentication/models.js';\n// Domain normalization is part of connection selection and repository resolution; consumers should use the\n// same implementation rather than importing an internal utility subpath or maintaining a divergent copy.\nexport { areDomainsOnSameHost, hostFromDomain } from './utils/domain.utils.js';\n\n// Convenience: wrap a static access token (env var, CLI flag, secret manager)\n// as an `IntegrationAuthenticationProvider`. For OAuth/refresh flows, implement\n// the interface directly — this helper is for non-interactive consumers only.\nexport {\n\tcreateManualTokenAuthProvider,\n\ttype ManualTokenAuthProviderOptions,\n} from './authentication/manualTokenProvider.js';\n\nexport {\n\tGitCloudHostIntegrationId,\n\tGitSelfManagedHostIntegrationId,\n\tIssuesCloudHostIntegrationId,\n\tIssuesSelfManagedHostIntegrationId,\n\tisIntegrationId,\n\tisSupportedCloudIntegrationId,\n} from './constants.js';\n\n// Neutral pagination + warning result types the Kepler ProviderBackend adapter maps to its own DTOs.\n// These carry no `@gitkraken/provider-apis` types, so consumers depend only on `@gitkraken/core-gitlens`.\nexport type {\n\tConnectionStateChangeEvent,\n\tProviderBroadenResult,\n\tProviderPagedResult,\n\tProviderPageInfo,\n\tProviderResult,\n\tProviderSweepResult,\n\tProviderWarning,\n\tProviderWarningCause,\n\tProviderWarningCauseReason,\n\tProviderWarningKind,\n\tProviderWarningOmission,\n\tProviderWarningOmissionKind,\n\tProviderWarningOmissionRecovery,\n\tProviderWarningOmissionScope,\n\tProviderWarningScope,\n\tProviderWarningSelector,\n\tProviderWarningUnreadableItems,\n\tProviderOrganization,\n\tProviderRepositoryShape,\n\tRepositoryIdentity,\n\tRepositoryResolution,\n\tRepositoryResolutionStatus,\n\tResolveRepositoryResult,\n} from './results.js';\n// Runtime enums — re-exported as values (not `export type`) so consumers can read their members.\nexport { IssueFilter, PullRequestFilter } from './providerFilters.js';\n// The filtered issue search's criteria model and the capability table that says which of it a provider honors.\n// String unions and plain interfaces, so a consumer builds criteria without importing an internal subpath.\nexport type { IssueSearchCapabilities, IssueSearchCriteria, IssueSearchRelationship } from './providerFilters.js';\n// Account-wide pull-request search criteria and the per-provider capability table.\nexport type { PullRequestSearchCapabilities, PullRequestSearchCriteria } from './providerFilters.js';\n// The count-only issue and pull-request probes' input and result shapes.\nexport type {\n\tIssueCountResult,\n\tIssueCountScope,\n\tPullRequestCountResult,\n\tPullRequestCountScope,\n} from './reads/counts.js';\nexport type { IssueBatchResult, IssueBatchTarget } from './reads/issueBatch.js';\nexport type { PullRequestBatchResult, PullRequestBatchTarget } from './reads/pullRequestBatch.js';\nexport type { IssueEtagInclude, PullRequestEtagInclude } from './models/integration.js';\nexport type { PullRequestBranchResult, PullRequestBranchTarget } from './reads/pullRequestBranches.js';\n// The current-account read's result, and the account shape every identity-bearing read already returns.\nexport type { CurrentAccountResult } from './reads/currentAccount.js';\nexport type { Account } from '@gitlens/git/models/author.js';\n// Cross-provider PR/issue state filters (string unions in the git models).\nexport type { PullRequestStateFilter } from '@gitlens/git/models/pullRequest.js';\nexport type { IssueStateFilter } from '@gitlens/git/models/issue.js';\n// Which read produced a row, and which of its fields that read fetched.\nexport type { PullRequestProjection } from '@gitlens/git/models/pullRequest.js';\nexport type { IssueProjection } from '@gitlens/git/models/issue.js';\nexport type { FieldPresence, IssueFieldGroup, PullRequestFieldGroup } from './fieldPresence.js';\nexport { getIssueFieldPresence, getPullRequestFieldPresence } from './fieldPresence.js';\n"],"mappings":";;;;;;;;;;AAiEA,SAAS,aAAgB,QAA4E;CACpG,OAAO,OAAO,IAAI,gBAAgB,CAAC,CAAC,CAAC;AACtC;AAEA,MAAM,mCAA6D;CAClE,wBAAwB,OAAO,cAAc,WAAW,aAAa,MAAM;CAC3E,6BAA6B,OAAO,cAAc,WAAW,aAAa,MAAM;CAChF,uBAAuB,MAAM,OAAO,cAAc,WAAW,aAAa,MAAM;CAChF,0BAA0B,SAAS,OAAO,cAAc,WAAW,aAAa,MAAM;CACtF,iBAAiB,KAAK,WAAW,cAAc,WAAW,aAAa,MAAM;CAC7E,wBAAwB,KAAK,OAAO,WAAW,cAAc,WAAW,aAAa,MAAM;CAC3F,WAAW,KAAK,WAAW,cAAc,WAAW,aAAa,MAAM;CACvE,oBAAoB,cAAc,WAAW,aAAa,MAAM;CAEhE,0BAA0B,CAAC;AAC5B;AAEA,SAAS,2BAA2B,OAA8E;CACjH,IAAI,SAAS,MAAM,OAAO;CAE1B,OAAO;EACN,GAAG;EACH,oBAAoB,aAAa,QAAQ,YACxC,MAAM,kBAAkB;GAAE,IAAI,YAAY;GAAI,QAAQ,YAAY;EAAO,GAAG,QAAQ,OAAO;CAC7F;AACD;;;;;;;;;;;;;AA+CA,SAAgB,yBAAyB,KAAoD;CAC5F,OAAO,yBAAyB;EAC/B,GAAG;EACH,OAAO,2BAA2B,IAAI,KAAK;CAC5C,CAAC;AACF"}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { Disposable } from "../../utils/disposable.js";
|
|
2
2
|
import { Event } from "../../utils/event.js";
|
|
3
|
+
import { RefSet } from "../../git/models/autolink.js";
|
|
3
4
|
import { RemoteProviderId } from "../../git/models/remoteProvider.js";
|
|
4
5
|
import { GitRemote } from "../../git/models/remote.js";
|
|
5
6
|
import { IssueSearchCriteria, IssueShape, IssueSorting, IssueStateFilter } from "../../git/models/issue.js";
|
|
6
7
|
import { PullRequest, PullRequestFilter, PullRequestSearchCriteria, PullRequestShape, PullRequestStateFilter } from "../../git/models/pullRequest.js";
|
|
7
8
|
import { Account } from "../../git/models/author.js";
|
|
8
9
|
import { GitHubApi } from "../git-github/api/github.js";
|
|
9
|
-
import { ConfiguredIntegrationDescriptor } from "./authentication/models.js";
|
|
10
|
+
import { ConfiguredIntegrationDescriptor, SessionPublication } from "./authentication/models.js";
|
|
10
11
|
import { CloudGitSelfManagedHostIntegrationIds, GitCloudHostIntegrationId, GitSelfManagedHostIntegrationId, IntegrationIds, IssuesCloudHostIntegrationId, SupportedCloudIntegrationIds } from "./constants.js";
|
|
11
12
|
import { Source } from "./telemetry.js";
|
|
12
13
|
import { ConfiguredIntegrationService, ConfiguredIntegrationsChangeEvent } from "./authentication/configuredIntegrationService.js";
|
|
@@ -23,7 +24,7 @@ import { SupportedFilters } from "./reads/filters.js";
|
|
|
23
24
|
import { IssueBatchResult, IssueBatchTarget } from "./reads/issueBatch.js";
|
|
24
25
|
import { PullRequestBatchResult, PullRequestBatchTarget } from "./reads/pullRequestBatch.js";
|
|
25
26
|
import { PullRequestBranchResult, PullRequestBranchTarget } from "./reads/pullRequestBranches.js";
|
|
26
|
-
import { ClosedPullRequestSweepOptions, ListOrgsOptions, ListProjectsOptions, ProviderBroadenOrg, PullRequestSweepOptions } from "./manager.js";
|
|
27
|
+
import { ClosedPullRequestSweepOptions, GetAutolinkReferencesOptions, ListOrgsOptions, ListProjectsOptions, ProviderBroadenOrg, PullRequestSweepOptions } from "./manager.js";
|
|
27
28
|
import "./providers/github/github.js";
|
|
28
29
|
import { ApiClients } from "./providers/apiClients.js";
|
|
29
30
|
import { IntegrationAuthenticationService } from "./authentication/integrationAuthenticationService.js";
|
|
@@ -156,9 +157,11 @@ export declare class IntegrationService implements Disposable, RepositoryResolut
|
|
|
156
157
|
* provider (the integration's primary-only sync path would never reach a secondary account), while a
|
|
157
158
|
* primary read syncs via the integration's own cloud-connection machinery. Either way the integration's cached
|
|
158
159
|
* discovery (a tracker's project list) is dropped, so the read sees projects created or deleted since.
|
|
159
|
-
* Best-effort
|
|
160
|
+
* Best-effort by default; strict discovery can require refresh success before trusting the resolved identity.
|
|
160
161
|
*/
|
|
161
|
-
forceRefreshIfRequested(integration: Integration, forceSync: boolean | undefined, connectionId: string | undefined
|
|
162
|
+
forceRefreshIfRequested(integration: Integration, forceSync: boolean | undefined, connectionId: string | undefined, options?: {
|
|
163
|
+
throwOnFailure?: boolean;
|
|
164
|
+
}): Promise<void>;
|
|
162
165
|
/**
|
|
163
166
|
* Lists the orgs/workspaces/groups (and issue-tracker resources) visible to the user, unified into
|
|
164
167
|
* {@link ProviderOrganization}. Scoped to `providerId` when given, otherwise fanned out over every
|
|
@@ -173,6 +176,7 @@ export declare class IntegrationService implements Disposable, RepositoryResolut
|
|
|
173
176
|
* trackers and Azure DevOps. Providers with no project tier (GitHub, GitLab, Bitbucket) contribute nothing.
|
|
174
177
|
*/
|
|
175
178
|
listProjects(options?: ListProjectsOptions): Promise<ProviderResult<ProviderOrganization>>;
|
|
179
|
+
getAutolinkReferences(options: GetAutolinkReferencesOptions): Promise<RefSet | undefined>;
|
|
176
180
|
/**
|
|
177
181
|
* Lists repositories under an org for a git-host provider, one page at a time. Pass `page` (1-based)
|
|
178
182
|
* to advance; the returned `cursor` is only meaningful for cursor-only hosts.
|
|
@@ -501,6 +505,7 @@ export declare class IntegrationService implements Disposable, RepositoryResolut
|
|
|
501
505
|
private getCloudConnectionState;
|
|
502
506
|
private findCachedById;
|
|
503
507
|
private getCachedForDomain;
|
|
508
|
+
onSessionPublishing(id: IntegrationIds, publication: SessionPublication, domains: readonly (string | undefined)[]): void;
|
|
504
509
|
private getConfiguredCloudConnection;
|
|
505
510
|
private getConfiguredConnectionDomain;
|
|
506
511
|
private getCloudPrimaryConnectionIdsByDomain;
|
|
@@ -17,6 +17,7 @@ import { providersMetadata } from "./providers/models.js";
|
|
|
17
17
|
import { ConfiguredIntegrationService } from "./authentication/configuredIntegrationService.js";
|
|
18
18
|
import { IntegrationAuthenticationService } from "./authentication/integrationAuthenticationService.js";
|
|
19
19
|
import { createApiClients } from "./providers/apiClients.js";
|
|
20
|
+
import { getAutolinkReferences } from "./reads/autolinks.js";
|
|
20
21
|
import { noConnectionWarning } from "./reads/warnings.js";
|
|
21
22
|
import { getSupportedFilters } from "./reads/filters.js";
|
|
22
23
|
import { broadenIssues } from "./reads/broaden.js";
|
|
@@ -66,7 +67,9 @@ var IntegrationService = class {
|
|
|
66
67
|
this.authenticationService = authenticationService;
|
|
67
68
|
this.configuredIntegrationService = configuredIntegrationService;
|
|
68
69
|
this.ctx = ctx;
|
|
69
|
-
this._disposable = fromDisposables(
|
|
70
|
+
this._disposable = fromDisposables(configuredIntegrationService.onWillChangeSession(({ integrationId, session, previousDomain }) => {
|
|
71
|
+
this.onSessionPublishing(integrationId, { session }, [session.domain, previousDomain]);
|
|
72
|
+
}), ctx.config.onDidChange((e) => {
|
|
70
73
|
if (e.remotes) this._ignoreSSLErrors.clear();
|
|
71
74
|
}), ctx.account.onDidChangeSessions(this.onAuthenticationSessionsChanged, this), ctx.account.onDidCheckIn(this.onUserCheckedIn, this), ctx.account.onDidChange(this.onSubscriptionChanged, this), this._onDidChangeIntegrationConnection.event(this.onIntegrationConnectionChanged, this));
|
|
72
75
|
}
|
|
@@ -551,11 +554,11 @@ var IntegrationService = class {
|
|
|
551
554
|
* provider (the integration's primary-only sync path would never reach a secondary account), while a
|
|
552
555
|
* primary read syncs via the integration's own cloud-connection machinery. Either way the integration's cached
|
|
553
556
|
* discovery (a tracker's project list) is dropped, so the read sees projects created or deleted since.
|
|
554
|
-
* Best-effort
|
|
557
|
+
* Best-effort by default; strict discovery can require refresh success before trusting the resolved identity.
|
|
555
558
|
*/
|
|
556
|
-
async forceRefreshIfRequested(integration, forceSync, connectionId) {
|
|
559
|
+
async forceRefreshIfRequested(integration, forceSync, connectionId, options) {
|
|
557
560
|
if (forceSync !== true) return;
|
|
558
|
-
integration.
|
|
561
|
+
integration.invalidateDiscoveryForConnection(connectionId);
|
|
559
562
|
try {
|
|
560
563
|
if (connectionId != null) {
|
|
561
564
|
const authProvider = await this.authenticationService.get(integration.authProvider.id);
|
|
@@ -567,9 +570,17 @@ var IntegrationService = class {
|
|
|
567
570
|
if (await authProvider?.getSession(descriptor, {
|
|
568
571
|
sync: true,
|
|
569
572
|
refetch: true
|
|
570
|
-
}) == null)
|
|
571
|
-
|
|
572
|
-
|
|
573
|
+
}) == null) {
|
|
574
|
+
if (options?.throwOnFailure) throw new Error("No refreshed provider session");
|
|
575
|
+
await authProvider?.deleteSession(descriptor);
|
|
576
|
+
}
|
|
577
|
+
} else {
|
|
578
|
+
const failure = await integration.syncCloudConnection("connected", true);
|
|
579
|
+
if (failure != null) throw failure;
|
|
580
|
+
}
|
|
581
|
+
} catch (ex) {
|
|
582
|
+
if (options?.throwOnFailure) throw ex;
|
|
583
|
+
}
|
|
573
584
|
}
|
|
574
585
|
/**
|
|
575
586
|
* Lists the orgs/workspaces/groups (and issue-tracker resources) visible to the user, unified into
|
|
@@ -589,6 +600,9 @@ var IntegrationService = class {
|
|
|
589
600
|
async listProjects(options) {
|
|
590
601
|
return listProjects(this, options);
|
|
591
602
|
}
|
|
603
|
+
async getAutolinkReferences(options) {
|
|
604
|
+
return getAutolinkReferences(this, options);
|
|
605
|
+
}
|
|
592
606
|
/**
|
|
593
607
|
* Lists repositories under an org for a git-host provider, one page at a time. Pass `page` (1-based)
|
|
594
608
|
* to advance; the returned `cursor` is only meaningful for cursor-only hosts.
|
|
@@ -869,6 +883,15 @@ var IntegrationService = class {
|
|
|
869
883
|
getCachedForDomain(id, domain) {
|
|
870
884
|
return isSelfManagedHostIntegrationId(id) ? this.getCached(id, domain) : this.findCachedById(id);
|
|
871
885
|
}
|
|
886
|
+
onSessionPublishing(id, publication, domains) {
|
|
887
|
+
const notified = /* @__PURE__ */ new Set();
|
|
888
|
+
for (const domain of domains) {
|
|
889
|
+
const integration = this.getCachedForDomain(id, domain == null ? domain : hostFromDomain(domain) ?? domain);
|
|
890
|
+
if (integration == null || notified.has(integration)) continue;
|
|
891
|
+
notified.add(integration);
|
|
892
|
+
integration.onSessionPublishing(publication);
|
|
893
|
+
}
|
|
894
|
+
}
|
|
872
895
|
getConfiguredCloudConnection(id, connectionId) {
|
|
873
896
|
const connection = this.configuredIntegrationService.getConfigured(id, { cloud: true }).find((c) => c.id === connectionId);
|
|
874
897
|
if (connection == null) throw new Error(`Connection '${connectionId}' is not configured for '${id}'`);
|