@gitkraken/core-gitlens 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (230) hide show
  1. package/CHANGELOG.md +13 -1
  2. package/README.md +13 -10
  3. package/dist/git/context.d.ts +4 -3
  4. package/dist/git/context.d.ts.map +1 -1
  5. package/dist/git/context.js.map +1 -1
  6. package/dist/git/providers/operations.d.ts +1 -0
  7. package/dist/git/providers/operations.d.ts.map +1 -1
  8. package/dist/git/providers/worktrees.d.ts +2 -0
  9. package/dist/git/providers/worktrees.d.ts.map +1 -1
  10. package/dist/git/utils/conflictResolution.utils.d.ts +32 -0
  11. package/dist/git/utils/conflictResolution.utils.d.ts.map +1 -1
  12. package/dist/git/utils/conflictResolution.utils.js +95 -0
  13. package/dist/git/utils/conflictResolution.utils.js.map +1 -1
  14. package/dist/git-cli/providers/operations.d.ts +1 -0
  15. package/dist/git-cli/providers/operations.d.ts.map +1 -1
  16. package/dist/git-cli/providers/operations.js +22 -1
  17. package/dist/git-cli/providers/operations.js.map +1 -1
  18. package/dist/git-cli/providers/worktrees.d.ts +2 -0
  19. package/dist/git-cli/providers/worktrees.d.ts.map +1 -1
  20. package/dist/git-cli/providers/worktrees.js +3 -0
  21. package/dist/git-cli/providers/worktrees.js.map +1 -1
  22. package/dist/plus/ai/utils/ai.utils.js +5 -5
  23. package/dist/plus/ai/utils/ai.utils.js.map +1 -1
  24. package/dist/plus/git-github/api/github.d.ts +6 -13
  25. package/dist/plus/git-github/api/github.d.ts.map +1 -1
  26. package/dist/plus/git-github/api/github.js +5 -10
  27. package/dist/plus/git-github/api/github.js.map +1 -1
  28. package/dist/plus/integrations/authentication/cloudIntegrationService.d.ts +11 -0
  29. package/dist/plus/integrations/authentication/cloudIntegrationService.d.ts.map +1 -0
  30. package/dist/plus/integrations/authentication/cloudIntegrationService.js +90 -0
  31. package/dist/plus/integrations/authentication/cloudIntegrationService.js.map +1 -0
  32. package/dist/plus/integrations/authentication/configuredIntegrationService.d.ts +67 -0
  33. package/dist/plus/integrations/authentication/configuredIntegrationService.d.ts.map +1 -0
  34. package/dist/plus/integrations/authentication/configuredIntegrationService.js +295 -0
  35. package/dist/plus/integrations/authentication/configuredIntegrationService.js.map +1 -0
  36. package/dist/plus/integrations/authentication/integrationAuthenticationProvider.d.ts +92 -0
  37. package/dist/plus/integrations/authentication/integrationAuthenticationProvider.d.ts.map +1 -0
  38. package/dist/plus/integrations/authentication/integrationAuthenticationProvider.js +185 -0
  39. package/dist/plus/integrations/authentication/integrationAuthenticationProvider.js.map +1 -0
  40. package/dist/plus/integrations/authentication/integrationAuthenticationService.d.ts +62 -0
  41. package/dist/plus/integrations/authentication/integrationAuthenticationService.d.ts.map +1 -0
  42. package/dist/plus/integrations/authentication/integrationAuthenticationService.js +122 -0
  43. package/dist/plus/integrations/authentication/integrationAuthenticationService.js.map +1 -0
  44. package/dist/plus/integrations/authentication/manualTokenProvider.d.ts +15 -0
  45. package/dist/plus/integrations/authentication/manualTokenProvider.d.ts.map +1 -0
  46. package/dist/plus/integrations/authentication/manualTokenProvider.js +49 -0
  47. package/dist/plus/integrations/authentication/manualTokenProvider.js.map +1 -0
  48. package/dist/plus/integrations/authentication/models.d.ts +87 -0
  49. package/dist/plus/integrations/authentication/models.d.ts.map +1 -0
  50. package/dist/plus/integrations/authentication/models.js +64 -0
  51. package/dist/plus/integrations/authentication/models.js.map +1 -0
  52. package/dist/plus/integrations/constants.d.ts +47 -0
  53. package/dist/plus/integrations/constants.d.ts.map +1 -0
  54. package/dist/plus/integrations/constants.js +128 -0
  55. package/dist/plus/integrations/constants.js.map +1 -0
  56. package/dist/plus/integrations/context.d.ts +354 -0
  57. package/dist/plus/integrations/context.d.ts.map +1 -0
  58. package/dist/plus/integrations/context.js +2 -0
  59. package/dist/plus/integrations/context.js.map +1 -0
  60. package/dist/plus/integrations/errors.d.ts +14 -0
  61. package/dist/plus/integrations/errors.d.ts.map +1 -0
  62. package/dist/plus/integrations/errors.js +19 -0
  63. package/dist/plus/integrations/errors.js.map +1 -0
  64. package/dist/plus/integrations/index.d.ts +32 -0
  65. package/dist/plus/integrations/index.d.ts.map +1 -0
  66. package/dist/plus/integrations/index.js +62 -0
  67. package/dist/plus/integrations/index.js.map +1 -0
  68. package/dist/plus/integrations/integrationService.d.ts +98 -0
  69. package/dist/plus/integrations/integrationService.d.ts.map +1 -0
  70. package/dist/plus/integrations/integrationService.js +627 -0
  71. package/dist/plus/integrations/integrationService.js.map +1 -0
  72. package/dist/plus/integrations/models/gitHostIntegration.d.ts +82 -0
  73. package/dist/plus/integrations/models/gitHostIntegration.d.ts.map +1 -0
  74. package/dist/plus/integrations/models/gitHostIntegration.js +522 -0
  75. package/dist/plus/integrations/models/gitHostIntegration.js.map +1 -0
  76. package/dist/plus/integrations/models/integration.d.ts +127 -0
  77. package/dist/plus/integrations/models/integration.d.ts.map +1 -0
  78. package/dist/plus/integrations/models/integration.js +456 -0
  79. package/dist/plus/integrations/models/integration.js.map +1 -0
  80. package/dist/plus/integrations/models/issuesIntegration.d.ts +28 -0
  81. package/dist/plus/integrations/models/issuesIntegration.d.ts.map +1 -0
  82. package/dist/plus/integrations/models/issuesIntegration.js +101 -0
  83. package/dist/plus/integrations/models/issuesIntegration.js.map +1 -0
  84. package/dist/plus/integrations/providers/apiClients.d.ts +25 -0
  85. package/dist/plus/integrations/providers/apiClients.d.ts.map +1 -0
  86. package/dist/plus/integrations/providers/apiClients.js +39 -0
  87. package/dist/plus/integrations/providers/apiClients.js.map +1 -0
  88. package/dist/plus/integrations/providers/azure/azure.d.ts +47 -0
  89. package/dist/plus/integrations/providers/azure/azure.d.ts.map +1 -0
  90. package/dist/plus/integrations/providers/azure/azure.js +444 -0
  91. package/dist/plus/integrations/providers/azure/azure.js.map +1 -0
  92. package/dist/plus/integrations/providers/azure/models.d.ts +286 -0
  93. package/dist/plus/integrations/providers/azure/models.d.ts.map +1 -0
  94. package/dist/plus/integrations/providers/azure/models.js +203 -0
  95. package/dist/plus/integrations/providers/azure/models.js.map +1 -0
  96. package/dist/plus/integrations/providers/azureDevOps.d.ts +95 -0
  97. package/dist/plus/integrations/providers/azureDevOps.d.ts.map +1 -0
  98. package/dist/plus/integrations/providers/azureDevOps.js +432 -0
  99. package/dist/plus/integrations/providers/azureDevOps.js.map +1 -0
  100. package/dist/plus/integrations/providers/bitbucket/bitbucket.d.ts +42 -0
  101. package/dist/plus/integrations/providers/bitbucket/bitbucket.d.ts.map +1 -0
  102. package/dist/plus/integrations/providers/bitbucket/bitbucket.js +513 -0
  103. package/dist/plus/integrations/providers/bitbucket/bitbucket.js.map +1 -0
  104. package/dist/plus/integrations/providers/bitbucket/models.d.ts +222 -0
  105. package/dist/plus/integrations/providers/bitbucket/models.d.ts.map +1 -0
  106. package/dist/plus/integrations/providers/bitbucket/models.js +158 -0
  107. package/dist/plus/integrations/providers/bitbucket/models.js.map +1 -0
  108. package/dist/plus/integrations/providers/bitbucket-server/models.d.ts +120 -0
  109. package/dist/plus/integrations/providers/bitbucket-server/models.d.ts.map +1 -0
  110. package/dist/plus/integrations/providers/bitbucket-server/models.js +111 -0
  111. package/dist/plus/integrations/providers/bitbucket-server/models.js.map +1 -0
  112. package/dist/plus/integrations/providers/bitbucket-server.d.ts +60 -0
  113. package/dist/plus/integrations/providers/bitbucket-server.d.ts.map +1 -0
  114. package/dist/plus/integrations/providers/bitbucket-server.js +138 -0
  115. package/dist/plus/integrations/providers/bitbucket-server.js.map +1 -0
  116. package/dist/plus/integrations/providers/bitbucket.d.ts +50 -0
  117. package/dist/plus/integrations/providers/bitbucket.d.ts.map +1 -0
  118. package/dist/plus/integrations/providers/bitbucket.js +181 -0
  119. package/dist/plus/integrations/providers/bitbucket.js.map +1 -0
  120. package/dist/plus/integrations/providers/github/github.d.ts +5 -0
  121. package/dist/plus/integrations/providers/github/github.d.ts.map +1 -0
  122. package/dist/plus/integrations/providers/github/github.js +47 -0
  123. package/dist/plus/integrations/providers/github/github.js.map +1 -0
  124. package/dist/plus/integrations/providers/github/github.utils.d.ts +11 -0
  125. package/dist/plus/integrations/providers/github/github.utils.d.ts.map +1 -0
  126. package/dist/plus/integrations/providers/github/github.utils.js +6 -0
  127. package/dist/plus/integrations/providers/github/github.utils.js.map +1 -0
  128. package/dist/plus/integrations/providers/github/models.d.ts +3 -0
  129. package/dist/plus/integrations/providers/github/models.d.ts.map +1 -0
  130. package/dist/plus/integrations/providers/github/models.js +2 -0
  131. package/dist/plus/integrations/providers/github/models.js.map +1 -0
  132. package/dist/plus/integrations/providers/github.d.ts +73 -0
  133. package/dist/plus/integrations/providers/github.d.ts.map +1 -0
  134. package/dist/plus/integrations/providers/github.js +160 -0
  135. package/dist/plus/integrations/providers/github.js.map +1 -0
  136. package/dist/plus/integrations/providers/gitlab/gitlab.d.ts +63 -0
  137. package/dist/plus/integrations/providers/gitlab/gitlab.d.ts.map +1 -0
  138. package/dist/plus/integrations/providers/gitlab/gitlab.js +828 -0
  139. package/dist/plus/integrations/providers/gitlab/gitlab.js.map +1 -0
  140. package/dist/plus/integrations/providers/gitlab/gitlab.utils.d.ts +21 -0
  141. package/dist/plus/integrations/providers/gitlab/gitlab.utils.d.ts.map +1 -0
  142. package/dist/plus/integrations/providers/gitlab/gitlab.utils.js +45 -0
  143. package/dist/plus/integrations/providers/gitlab/gitlab.utils.js.map +1 -0
  144. package/dist/plus/integrations/providers/gitlab/models.d.ts +128 -0
  145. package/dist/plus/integrations/providers/gitlab/models.d.ts.map +1 -0
  146. package/dist/plus/integrations/providers/gitlab/models.js +96 -0
  147. package/dist/plus/integrations/providers/gitlab/models.js.map +1 -0
  148. package/dist/plus/integrations/providers/gitlab.d.ts +79 -0
  149. package/dist/plus/integrations/providers/gitlab.d.ts.map +1 -0
  150. package/dist/plus/integrations/providers/gitlab.js +253 -0
  151. package/dist/plus/integrations/providers/gitlab.js.map +1 -0
  152. package/dist/plus/integrations/providers/jira.d.ts +46 -0
  153. package/dist/plus/integrations/providers/jira.d.ts.map +1 -0
  154. package/dist/plus/integrations/providers/jira.js +255 -0
  155. package/dist/plus/integrations/providers/jira.js.map +1 -0
  156. package/dist/plus/integrations/providers/linear.d.ts +47 -0
  157. package/dist/plus/integrations/providers/linear.d.ts.map +1 -0
  158. package/dist/plus/integrations/providers/linear.js +198 -0
  159. package/dist/plus/integrations/providers/linear.js.map +1 -0
  160. package/dist/plus/integrations/providers/models.d.ts +433 -0
  161. package/dist/plus/integrations/providers/models.d.ts.map +1 -0
  162. package/dist/plus/integrations/providers/models.js +602 -0
  163. package/dist/plus/integrations/providers/models.js.map +1 -0
  164. package/dist/plus/integrations/providers/providersApi.d.ts +129 -0
  165. package/dist/plus/integrations/providers/providersApi.d.ts.map +1 -0
  166. package/dist/plus/integrations/providers/providersApi.js +602 -0
  167. package/dist/plus/integrations/providers/providersApi.js.map +1 -0
  168. package/dist/plus/integrations/providers/utils.d.ts +54 -0
  169. package/dist/plus/integrations/providers/utils.d.ts.map +1 -0
  170. package/dist/plus/integrations/providers/utils.js +262 -0
  171. package/dist/plus/integrations/providers/utils.js.map +1 -0
  172. package/dist/plus/integrations/telemetry.d.ts +26 -0
  173. package/dist/plus/integrations/telemetry.d.ts.map +1 -0
  174. package/dist/plus/integrations/telemetry.js +11 -0
  175. package/dist/plus/integrations/telemetry.js.map +1 -0
  176. package/dist/plus/integrations/utils/integration.utils.d.ts +14 -0
  177. package/dist/plus/integrations/utils/integration.utils.d.ts.map +1 -0
  178. package/dist/plus/integrations/utils/integration.utils.js +111 -0
  179. package/dist/plus/integrations/utils/integration.utils.js.map +1 -0
  180. package/dist/utils/disposable.d.ts +15 -2
  181. package/dist/utils/disposable.d.ts.map +1 -1
  182. package/dist/utils/disposable.js.map +1 -1
  183. package/package.json +43 -2
  184. package/src/git/context.ts +4 -3
  185. package/src/git/providers/operations.ts +1 -1
  186. package/src/git/providers/worktrees.ts +14 -2
  187. package/src/git/utils/conflictResolution.utils.ts +126 -0
  188. package/src/git-cli/providers/operations.ts +22 -2
  189. package/src/git-cli/providers/worktrees.ts +17 -2
  190. package/src/plus/ai/utils/ai.utils.ts +5 -5
  191. package/src/plus/git-github/api/github.ts +13 -25
  192. package/src/plus/integrations/authentication/cloudIntegrationService.ts +120 -0
  193. package/src/plus/integrations/authentication/configuredIntegrationService.ts +414 -0
  194. package/src/plus/integrations/authentication/integrationAuthenticationProvider.ts +289 -0
  195. package/src/plus/integrations/authentication/integrationAuthenticationService.ts +144 -0
  196. package/src/plus/integrations/authentication/manualTokenProvider.ts +72 -0
  197. package/src/plus/integrations/authentication/models.ts +168 -0
  198. package/src/plus/integrations/constants.ts +169 -0
  199. package/src/plus/integrations/context.ts +383 -0
  200. package/src/plus/integrations/errors.ts +35 -0
  201. package/src/plus/integrations/index.ts +119 -0
  202. package/src/plus/integrations/integrationService.ts +924 -0
  203. package/src/plus/integrations/models/gitHostIntegration.ts +738 -0
  204. package/src/plus/integrations/models/integration.ts +657 -0
  205. package/src/plus/integrations/models/issuesIntegration.ts +124 -0
  206. package/src/plus/integrations/providers/apiClients.ts +72 -0
  207. package/src/plus/integrations/providers/azure/azure.ts +691 -0
  208. package/src/plus/integrations/providers/azure/models.ts +605 -0
  209. package/src/plus/integrations/providers/azureDevOps.ts +677 -0
  210. package/src/plus/integrations/providers/bitbucket/bitbucket.ts +774 -0
  211. package/src/plus/integrations/providers/bitbucket/models.ts +445 -0
  212. package/src/plus/integrations/providers/bitbucket-server/models.ts +252 -0
  213. package/src/plus/integrations/providers/bitbucket-server.ts +282 -0
  214. package/src/plus/integrations/providers/bitbucket.ts +350 -0
  215. package/src/plus/integrations/providers/github/github.ts +64 -0
  216. package/src/plus/integrations/providers/github/github.utils.ts +23 -0
  217. package/src/plus/integrations/providers/github/models.ts +29 -0
  218. package/src/plus/integrations/providers/github.ts +366 -0
  219. package/src/plus/integrations/providers/gitlab/gitlab.ts +1210 -0
  220. package/src/plus/integrations/providers/gitlab/gitlab.utils.ts +71 -0
  221. package/src/plus/integrations/providers/gitlab/models.ts +257 -0
  222. package/src/plus/integrations/providers/gitlab.ts +473 -0
  223. package/src/plus/integrations/providers/jira.ts +359 -0
  224. package/src/plus/integrations/providers/linear.ts +275 -0
  225. package/src/plus/integrations/providers/models.ts +1114 -0
  226. package/src/plus/integrations/providers/providersApi.ts +1126 -0
  227. package/src/plus/integrations/providers/utils.ts +359 -0
  228. package/src/plus/integrations/telemetry.ts +29 -0
  229. package/src/plus/integrations/utils/integration.utils.ts +138 -0
  230. package/src/utils/disposable.ts +15 -2
@@ -0,0 +1,359 @@
1
+ import type { AnyEntityIdentifierInput, EntityIdentifier } from '@gitkraken/provider-apis';
2
+ import { EntityIdentifierProviderType, EntityType, EntityVersion } from '@gitkraken/provider-apis';
3
+ import type { Issue, IssueShape } from '../../../git/models/issue.js';
4
+ import type { IssueOrPullRequest } from '../../../git/models/issueOrPullRequest.js';
5
+ import type { PullRequest } from '../../../git/models/pullRequest.js';
6
+ import type {
7
+ IssueResourceDescriptor,
8
+ RepositoryDescriptor,
9
+ ResourceDescriptor,
10
+ } from '../../../git/models/resourceDescriptor.js';
11
+ import { isIssueResourceDescriptor, isRepositoryDescriptor } from '../../../git/utils/resourceDescriptor.utils.js';
12
+ import { Logger } from '../../../utils/logger.js';
13
+ import type { IntegrationIds } from '../constants.js';
14
+ import {
15
+ GitCloudHostIntegrationId,
16
+ GitSelfManagedHostIntegrationId,
17
+ IssuesCloudHostIntegrationId,
18
+ } from '../constants.js';
19
+ import { isCloudGitSelfManagedHostIntegrationId } from '../utils/integration.utils.js';
20
+ import type { AzureProjectInputDescriptor } from './azure/models.js';
21
+ import type { GitConfigEntityIdentifier } from './models.js';
22
+ import { isGitHubDotCom, isGitLabDotCom } from './models.js';
23
+
24
+ /**
25
+ * Forward-compatible structural shape of the host's `LaunchpadItem`. The package
26
+ * uses this for narrowing inside {@link getEntityIdentifierInput}; the host's
27
+ * actual `LaunchpadItem` (in `src/plus/launchpad/launchpadProvider.ts`) carries
28
+ * many more fields. The declared shape only includes fields integrations inspect.
29
+ */
30
+ type LaunchpadItem = {
31
+ uuid: string;
32
+ type: 'issue' | 'pullrequest';
33
+ graphQLId?: string;
34
+ provider: { id: string; domain?: string };
35
+ underlyingPullRequest?: {
36
+ id: string;
37
+ project?: { id: string; resourceName?: string };
38
+ repository?: { id?: string };
39
+ };
40
+ };
41
+
42
+ function isLaunchpadItem(item: IssueOrPullRequest | LaunchpadItem): item is LaunchpadItem {
43
+ return (item as LaunchpadItem).uuid !== undefined;
44
+ }
45
+
46
+ function isIssue(item: IssueOrPullRequest | LaunchpadItem): item is Issue {
47
+ return item.type === 'issue';
48
+ }
49
+
50
+ export function getEntityIdentifierInput(entity: Issue | PullRequest | LaunchpadItem): AnyEntityIdentifierInput {
51
+ let entityType = EntityType.Issue;
52
+ if (entity.type === 'pullrequest') {
53
+ entityType = EntityType.PullRequest;
54
+ }
55
+
56
+ let provider = fromStringToEntityIdentifierProviderType(entity.provider.id);
57
+ let domain = null;
58
+ if (provider === EntityIdentifierProviderType.Github && !isGitHubDotCom(entity.provider.domain)) {
59
+ provider = EntityIdentifierProviderType.GithubEnterprise;
60
+ domain = entity.provider.domain ?? null;
61
+ }
62
+ if (provider === EntityIdentifierProviderType.Gitlab && !isGitLabDotCom(entity.provider.domain)) {
63
+ provider = EntityIdentifierProviderType.GitlabSelfHosted;
64
+ domain = entity.provider.domain ?? null;
65
+ }
66
+ if (provider === EntityIdentifierProviderType.AzureDevOpsServer) {
67
+ domain = entity.provider.domain ?? null;
68
+ }
69
+
70
+ let projectId = null;
71
+ let resourceId = null;
72
+ let organizationName = null;
73
+ let repoId = null;
74
+ if (provider === EntityIdentifierProviderType.Jira) {
75
+ if (!isIssue(entity) || entity.project == null) {
76
+ throw new Error('Jira issues must have a project');
77
+ }
78
+
79
+ projectId = entity.project.id;
80
+ resourceId = entity.project.resourceId;
81
+ } else if (
82
+ provider === EntityIdentifierProviderType.Azure ||
83
+ provider === EntityIdentifierProviderType.AzureDevOpsServer
84
+ ) {
85
+ const project = isLaunchpadItem(entity) ? entity.underlyingPullRequest?.project : entity.project;
86
+ if (project == null) {
87
+ throw new Error('Azure issues and PRs must have a project to be encoded');
88
+ }
89
+
90
+ projectId = project.id;
91
+ organizationName = project.resourceName;
92
+ repoId = isLaunchpadItem(entity) ? entity.underlyingPullRequest?.repository?.id : entity.repository?.id;
93
+ if (entityType === EntityType.PullRequest && repoId == null) {
94
+ throw new Error('Azure PRs must have a repository ID to be encoded');
95
+ }
96
+ } else if (
97
+ provider === EntityIdentifierProviderType.Bitbucket ||
98
+ provider === EntityIdentifierProviderType.BitbucketServer
99
+ ) {
100
+ repoId = isLaunchpadItem(entity) ? entity.underlyingPullRequest?.repository?.id : entity.repository?.id;
101
+ }
102
+
103
+ let entityId = isLaunchpadItem(entity) ? entity.graphQLId! : entity.nodeId!;
104
+ if (
105
+ provider === EntityIdentifierProviderType.Azure ||
106
+ provider === EntityIdentifierProviderType.AzureDevOpsServer
107
+ ) {
108
+ entityId = (isLaunchpadItem(entity) ? entity.underlyingPullRequest?.id : entity.id) as string;
109
+ }
110
+
111
+ // `AnyEntityIdentifierInput` includes the catch-all `EntityIdentifier`
112
+ // variant which requires all fields, while each provider-specific variant
113
+ // requires a different subset. The function builds a polymorphic value
114
+ // that's correct at runtime per `provider` but the literal can't be
115
+ // structurally narrowed to any single variant. The 2-step cast through
116
+ // `unknown` is the documented escape for this discriminated-union pattern.
117
+ return {
118
+ accountOrOrgId: null, // needed for Trello issues, once supported
119
+ organizationName: organizationName, // needed for Azure issues and PRs, once supported
120
+ projectId: projectId, // needed for Jira issues, Trello issues, and Azure issues and PRs, once supported
121
+ repoId: repoId ?? null, // needed for Azure and BitBucket PRs, once supported
122
+ resourceId: resourceId, // needed for Jira issues
123
+ provider: provider,
124
+ entityType: entityType,
125
+ version: EntityVersion.One,
126
+ domain: domain,
127
+ entityId: entityId,
128
+ } as unknown as AnyEntityIdentifierInput;
129
+ }
130
+
131
+ export function getProviderIdFromEntityIdentifier(
132
+ entityIdentifier: EntityIdentifier | AnyEntityIdentifierInput | GitConfigEntityIdentifier,
133
+ ): IntegrationIds | undefined {
134
+ switch (entityIdentifier.provider) {
135
+ case EntityIdentifierProviderType.Github:
136
+ return GitCloudHostIntegrationId.GitHub;
137
+ case EntityIdentifierProviderType.GithubEnterprise:
138
+ return GitSelfManagedHostIntegrationId.CloudGitHubEnterprise;
139
+ case EntityIdentifierProviderType.Gitlab:
140
+ return GitCloudHostIntegrationId.GitLab;
141
+ case EntityIdentifierProviderType.GitlabSelfHosted:
142
+ return GitSelfManagedHostIntegrationId.CloudGitLabSelfHosted;
143
+ case EntityIdentifierProviderType.Jira:
144
+ return IssuesCloudHostIntegrationId.Jira;
145
+ case EntityIdentifierProviderType.Linear:
146
+ return IssuesCloudHostIntegrationId.Linear;
147
+ case EntityIdentifierProviderType.Azure:
148
+ return GitCloudHostIntegrationId.AzureDevOps;
149
+ case EntityIdentifierProviderType.AzureDevOpsServer:
150
+ return GitSelfManagedHostIntegrationId.AzureDevOpsServer;
151
+ case EntityIdentifierProviderType.Bitbucket:
152
+ return GitCloudHostIntegrationId.Bitbucket;
153
+ case EntityIdentifierProviderType.BitbucketServer:
154
+ return isGitConfigEntityIdentifier(entityIdentifier) && entityIdentifier.metadata.isCloudEnterprise
155
+ ? GitSelfManagedHostIntegrationId.BitbucketServer
156
+ : undefined;
157
+ default:
158
+ return undefined;
159
+ }
160
+ }
161
+
162
+ function fromStringToEntityIdentifierProviderType(str: string): EntityIdentifierProviderType {
163
+ switch (str) {
164
+ case 'github':
165
+ return EntityIdentifierProviderType.Github;
166
+ case 'cloud-github-enterprise':
167
+ return EntityIdentifierProviderType.GithubEnterprise;
168
+ case 'cloud-gitlab-self-hosted':
169
+ return EntityIdentifierProviderType.GitlabSelfHosted;
170
+ case 'gitlab':
171
+ return EntityIdentifierProviderType.Gitlab;
172
+ case 'jira':
173
+ return EntityIdentifierProviderType.Jira;
174
+ case 'linear':
175
+ return EntityIdentifierProviderType.Linear;
176
+ case 'azure':
177
+ case 'azureDevOps':
178
+ case 'azure-devops':
179
+ return EntityIdentifierProviderType.Azure;
180
+ case GitSelfManagedHostIntegrationId.AzureDevOpsServer:
181
+ return EntityIdentifierProviderType.AzureDevOpsServer;
182
+ case 'bitbucket':
183
+ return EntityIdentifierProviderType.Bitbucket;
184
+ case 'bitbucket-server':
185
+ return EntityIdentifierProviderType.BitbucketServer;
186
+ default:
187
+ throw new Error(`Unknown provider type '${str}'`);
188
+ }
189
+ }
190
+
191
+ export function encodeIssueOrPullRequestForGitConfig(
192
+ entity: Issue | PullRequest,
193
+ owner: RepositoryDescriptor | IssueResourceDescriptor,
194
+ ): GitConfigEntityIdentifier {
195
+ const encodedOwner: GitConfigEntityIdentifier['metadata']['owner'] = {
196
+ key: owner.key,
197
+ name: owner.name,
198
+ id: undefined,
199
+ owner: undefined,
200
+ };
201
+ if (isRepositoryDescriptor(owner)) {
202
+ encodedOwner.owner = owner.owner;
203
+ } else if (isIssueResourceDescriptor(owner)) {
204
+ encodedOwner.id = owner.id;
205
+ } else {
206
+ throw new Error('Invalid owner');
207
+ }
208
+
209
+ return {
210
+ ...getEntityIdentifierInput(entity),
211
+ metadata: {
212
+ id: entity.id,
213
+ owner: encodedOwner,
214
+ createdDate: new Date().toISOString(),
215
+ isCloudEnterprise: isCloudGitSelfManagedHostIntegrationId(entity.provider.id as IntegrationIds),
216
+ },
217
+ };
218
+ }
219
+
220
+ export function isGitConfigEntityIdentifier(entity: unknown): entity is GitConfigEntityIdentifier {
221
+ return (
222
+ entity != null &&
223
+ typeof entity === 'object' &&
224
+ 'provider' in entity &&
225
+ entity.provider != null &&
226
+ 'entityType' in entity &&
227
+ entity.entityType != null &&
228
+ 'version' in entity &&
229
+ entity.version != null &&
230
+ 'entityId' in entity &&
231
+ entity.entityId != null &&
232
+ 'metadata' in entity &&
233
+ entity.metadata != null &&
234
+ typeof entity.metadata === 'object' &&
235
+ 'id' in entity.metadata &&
236
+ entity.metadata.id != null &&
237
+ 'owner' in entity.metadata &&
238
+ entity.metadata.owner != null &&
239
+ 'createdDate' in entity.metadata &&
240
+ entity.metadata.createdDate != null
241
+ );
242
+ }
243
+
244
+ export function isGitConfigEntityIdentifiers(entities: unknown): entities is GitConfigEntityIdentifier[] {
245
+ return Array.isArray(entities) && entities.every(entity => isGitConfigEntityIdentifier(entity));
246
+ }
247
+
248
+ export function decodeEntityIdentifiersFromGitConfig(str: string): GitConfigEntityIdentifier[] {
249
+ const decoded = JSON.parse(str);
250
+
251
+ if (!isGitConfigEntityIdentifiers(decoded)) {
252
+ debugger;
253
+ Logger.error('Invalid entity identifiers in git config');
254
+ return [];
255
+ }
256
+
257
+ for (const decodedEntity of decoded) {
258
+ if (
259
+ decodedEntity.provider === EntityIdentifierProviderType.Jira &&
260
+ (decodedEntity.resourceId == null || decodedEntity.projectId == null)
261
+ ) {
262
+ debugger;
263
+ Logger.error('Invalid Jira issue in git config');
264
+ }
265
+ }
266
+
267
+ return decoded;
268
+ }
269
+
270
+ interface IssueResolvableIntegration {
271
+ getIssue(owner: unknown, id: string): Promise<Issue | undefined>;
272
+ }
273
+
274
+ export async function getIssueFromGitConfigEntityIdentifier(
275
+ resolveIntegration: (id: IntegrationIds) => Promise<IssueResolvableIntegration | undefined>,
276
+ identifier: GitConfigEntityIdentifier,
277
+ options?: {
278
+ /** Only return a value already in the local cache. No remote fetch — returns undefined on cache miss. */
279
+ cached?: boolean;
280
+ /**
281
+ * Host-supplied cache reader used when {@link cached} is set. The package is cache-agnostic, so the
282
+ * host (which owns the cache) provides this to satisfy a cache-only read. When omitted, `cached`
283
+ * yields undefined rather than falling through to a remote fetch.
284
+ */
285
+ peekCachedIssue?: (
286
+ integration: IssueResolvableIntegration | undefined,
287
+ resource: ResourceDescriptor,
288
+ id: string,
289
+ ) => Issue | undefined;
290
+ },
291
+ ): Promise<Issue | undefined> {
292
+ if (identifier.entityType !== EntityType.Issue) {
293
+ return undefined;
294
+ }
295
+
296
+ // TODO: Centralize where we represent all supported providers for issues
297
+ if (
298
+ identifier.provider !== EntityIdentifierProviderType.Jira &&
299
+ identifier.provider !== EntityIdentifierProviderType.Linear &&
300
+ identifier.provider !== EntityIdentifierProviderType.Github &&
301
+ identifier.provider !== EntityIdentifierProviderType.Gitlab &&
302
+ identifier.provider !== EntityIdentifierProviderType.GithubEnterprise &&
303
+ identifier.provider !== EntityIdentifierProviderType.GitlabSelfHosted &&
304
+ identifier.provider !== EntityIdentifierProviderType.Bitbucket &&
305
+ identifier.provider !== EntityIdentifierProviderType.BitbucketServer &&
306
+ identifier.provider !== EntityIdentifierProviderType.AzureDevOpsServer &&
307
+ identifier.provider !== EntityIdentifierProviderType.Azure
308
+ ) {
309
+ return undefined;
310
+ }
311
+
312
+ const integrationId = getProviderIdFromEntityIdentifier(identifier);
313
+ if (integrationId == null) {
314
+ return undefined;
315
+ }
316
+
317
+ const integration = await resolveIntegration(integrationId);
318
+
319
+ const resource: ResourceDescriptor = {
320
+ id: identifier.metadata.owner.id,
321
+ key: identifier.metadata.owner.key,
322
+ owner: identifier.metadata.owner.owner,
323
+ name: identifier.metadata.owner.name,
324
+ };
325
+
326
+ // Cache-only read (no remote fetch). The package can't reach the host cache directly, so defer to the
327
+ // host-supplied reader; without one, honor the no-fetch contract by returning undefined. The cache key
328
+ // is resource+id (the integration only affects the etag), so peek even when the integration is
329
+ // unresolvable — a still-cached issue must survive an unconfigured/disconnected integration.
330
+ if (options?.cached) {
331
+ return options.peekCachedIssue?.(integration, resource, identifier.metadata.id);
332
+ }
333
+
334
+ if (integration == null) {
335
+ return undefined;
336
+ }
337
+
338
+ return integration.getIssue(resource, identifier.metadata.id);
339
+ }
340
+
341
+ export function getIssueOwner(
342
+ issue: IssueShape,
343
+ ): RepositoryDescriptor | IssueResourceDescriptor | AzureProjectInputDescriptor | undefined {
344
+ const isAzure = ['azure', GitCloudHostIntegrationId.AzureDevOps, 'azure-devops'].includes(issue.provider.id);
345
+ return issue.repository
346
+ ? {
347
+ key: `${issue.repository.owner}/${issue.repository.repo}`,
348
+ owner: issue.repository.owner,
349
+ name: issue.repository.repo,
350
+ }
351
+ : issue.project
352
+ ? {
353
+ key: isAzure ? issue.project.id : issue.project.resourceId,
354
+ id: isAzure ? issue.project.id : issue.project.resourceId,
355
+ owner: isAzure ? issue.project.resourceName : undefined,
356
+ name: isAzure ? issue.project.name : issue.project.resourceName,
357
+ }
358
+ : undefined;
359
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Telemetry-source types used by the integrations package.
3
+ *
4
+ * Mirrors the shape of the host's `Source` / `Sources` types from
5
+ * `src/constants.telemetry.ts` but intentionally widens `source` to a plain
6
+ * `string` so the package doesn't depend on the host's enumerated union.
7
+ * The host passes its typed `Source` directly — TypeScript's structural
8
+ * subtyping accepts the narrower type here.
9
+ */
10
+ export type Source = {
11
+ source: string;
12
+ correlationId?: string;
13
+
14
+ detail?: unknown;
15
+ };
16
+
17
+ export type Sources = string;
18
+
19
+ /**
20
+ * Maps a telemetry `source`/`detail` to the `&context=` value the package appends when building
21
+ * cloud-connect URLs. Owned here in the package (the host no longer carries a duplicate copy).
22
+ */
23
+ export const sourceToContext: { [source: string]: string | undefined } = {
24
+ launchpad: 'launchpad',
25
+ };
26
+
27
+ export const detailToContext: { [detail: string]: string | undefined } = {
28
+ mcp: 'mcp',
29
+ };
@@ -0,0 +1,138 @@
1
+ import type { RemoteProvider, RemoteProviderId } from '../../../git/models/remoteProvider.js';
2
+ import type { CloudGitSelfManagedHostIntegrationIds, IntegrationIds } from '../constants.js';
3
+ import {
4
+ GitCloudHostIntegrationId,
5
+ GitSelfManagedHostIntegrationId,
6
+ IssuesCloudHostIntegrationId,
7
+ } from '../constants.js';
8
+ import type { GitHostIntegration } from '../models/gitHostIntegration.js';
9
+ import type { Integration, IntegrationConnectedKey } from '../models/integration.js';
10
+ import { isGitHubDotCom, isGitLabDotCom } from '../providers/models.js';
11
+
12
+ // These two domain checks live here (rather than in their provider modules) to
13
+ // break a top-level circular import. The provider modules synchronously read
14
+ // `providersMetadata[...]` at module init time, so importing from them while
15
+ // `providers/models.ts` is still loading triggers a TDZ on `providersMetadata`.
16
+ const azureCloudDomainRegex = /^dev\.azure\.com$|\bvisualstudio\.com$/i;
17
+ const bitbucketCloudDomainRegex = /^bitbucket\.org$/i;
18
+ function isAzureCloudDomain(domain: string | undefined): boolean {
19
+ return domain != null && azureCloudDomainRegex.test(domain);
20
+ }
21
+ function isBitbucketCloudDomain(domain: string | undefined): boolean {
22
+ return domain != null && bitbucketCloudDomainRegex.test(domain);
23
+ }
24
+
25
+ const selfHostedIntegrationIds: GitSelfManagedHostIntegrationId[] = [
26
+ GitSelfManagedHostIntegrationId.CloudGitHubEnterprise,
27
+ GitSelfManagedHostIntegrationId.CloudGitLabSelfHosted,
28
+ GitSelfManagedHostIntegrationId.BitbucketServer,
29
+ GitSelfManagedHostIntegrationId.AzureDevOpsServer,
30
+ ] as const;
31
+
32
+ export const supportedIntegrationIds: IntegrationIds[] = [
33
+ GitCloudHostIntegrationId.GitHub,
34
+ GitCloudHostIntegrationId.GitLab,
35
+ GitCloudHostIntegrationId.Bitbucket,
36
+ GitCloudHostIntegrationId.AzureDevOps,
37
+ IssuesCloudHostIntegrationId.Jira,
38
+ // Note: Trello is metadata-only (no auth provider), so it is intentionally absent — including it
39
+ // would make reset()'s ensureProvider() throw 'No authentication provider registered'.
40
+ ...selfHostedIntegrationIds,
41
+ ] as const;
42
+
43
+ export function convertRemoteProviderIdToIntegrationId(
44
+ remoteProviderId: RemoteProviderId,
45
+ ): GitCloudHostIntegrationId | GitSelfManagedHostIntegrationId | undefined {
46
+ switch (remoteProviderId) {
47
+ case 'azure-devops':
48
+ return GitCloudHostIntegrationId.AzureDevOps;
49
+ case 'bitbucket':
50
+ return GitCloudHostIntegrationId.Bitbucket;
51
+ case 'github':
52
+ return GitCloudHostIntegrationId.GitHub;
53
+ case 'gitlab':
54
+ return GitCloudHostIntegrationId.GitLab;
55
+ case 'bitbucket-server':
56
+ return GitSelfManagedHostIntegrationId.BitbucketServer;
57
+ default:
58
+ return undefined;
59
+ }
60
+ }
61
+
62
+ export function getIntegrationConnectedKey<T extends IntegrationIds>(
63
+ id: T,
64
+ domain?: string,
65
+ ): IntegrationConnectedKey<T> {
66
+ if (isGitSelfManagedHostIntegrationId(id)) {
67
+ if (!domain) {
68
+ throw new Error(`Domain is required for self-managed integration ID: ${id}`);
69
+ }
70
+ return `connected:${id}:${domain}` as IntegrationConnectedKey<T>;
71
+ }
72
+
73
+ return `connected:${id}` as IntegrationConnectedKey<T>;
74
+ }
75
+
76
+ export function getIntegrationIdForRemote(
77
+ provider: RemoteProvider | undefined,
78
+ ): GitCloudHostIntegrationId | GitSelfManagedHostIntegrationId | undefined {
79
+ switch (provider?.id) {
80
+ case 'azure-devops':
81
+ if (isAzureCloudDomain(provider.domain)) {
82
+ return GitCloudHostIntegrationId.AzureDevOps;
83
+ }
84
+ return provider.custom ? undefined : GitSelfManagedHostIntegrationId.AzureDevOpsServer;
85
+ case 'bitbucket':
86
+ case 'bitbucket-server':
87
+ if (isBitbucketCloudDomain(provider.domain)) {
88
+ return GitCloudHostIntegrationId.Bitbucket;
89
+ }
90
+ return GitSelfManagedHostIntegrationId.BitbucketServer;
91
+ case 'github':
92
+ if (provider.domain != null && !isGitHubDotCom(provider.domain)) {
93
+ return GitSelfManagedHostIntegrationId.CloudGitHubEnterprise;
94
+ }
95
+ return GitCloudHostIntegrationId.GitHub;
96
+ case 'gitlab':
97
+ if (provider.domain != null && !isGitLabDotCom(provider.domain)) {
98
+ return GitSelfManagedHostIntegrationId.CloudGitLabSelfHosted;
99
+ }
100
+ return GitCloudHostIntegrationId.GitLab;
101
+ default:
102
+ return undefined;
103
+ }
104
+ }
105
+
106
+ export function isCloudGitSelfManagedHostIntegrationId(
107
+ id: IntegrationIds,
108
+ ): id is CloudGitSelfManagedHostIntegrationIds {
109
+ switch (id) {
110
+ case GitSelfManagedHostIntegrationId.CloudGitHubEnterprise:
111
+ case GitSelfManagedHostIntegrationId.CloudGitLabSelfHosted:
112
+ case GitSelfManagedHostIntegrationId.BitbucketServer:
113
+ case GitSelfManagedHostIntegrationId.AzureDevOpsServer:
114
+ return true;
115
+ default:
116
+ return false;
117
+ }
118
+ }
119
+
120
+ export function isGitHostIntegration(integration: Integration): integration is GitHostIntegration {
121
+ return integration.type === 'git';
122
+ }
123
+
124
+ export function isGitCloudHostIntegrationId(id: IntegrationIds): id is GitCloudHostIntegrationId {
125
+ switch (id) {
126
+ case GitCloudHostIntegrationId.GitHub:
127
+ case GitCloudHostIntegrationId.GitLab:
128
+ case GitCloudHostIntegrationId.Bitbucket:
129
+ case GitCloudHostIntegrationId.AzureDevOps:
130
+ return true;
131
+ default:
132
+ return false;
133
+ }
134
+ }
135
+
136
+ export function isGitSelfManagedHostIntegrationId(id: IntegrationIds): id is GitSelfManagedHostIntegrationId {
137
+ return selfHostedIntegrationIds.includes(id as GitSelfManagedHostIntegrationId);
138
+ }
@@ -1,6 +1,19 @@
1
1
  import { once } from './function.js';
2
2
 
3
- export type UnifiedDisposable = { dispose: () => void } & Disposable;
3
+ /**
4
+ * Minimal disposable contract — a single `dispose(): void` method.
5
+ *
6
+ * Mirrors the shape of `vscode.Disposable` so vscode-free packages can name
7
+ * the contract without requiring lib.es2022's `[Symbol.dispose]`. Classes that
8
+ * already implement `dispose()` (the vscode-style) satisfy it without changes.
9
+ *
10
+ * Use {@link UnifiedDisposable} when you also need the `using`-statement
11
+ * (`Symbol.dispose`) protocol; everything else can stay on this looser type.
12
+ */
13
+
14
+ export type Disposable = { dispose: () => void };
15
+
16
+ export type UnifiedDisposable = { dispose: () => void } & globalThis.Disposable;
4
17
  export type UnifiedAsyncDisposable = { dispose: () => Promise<void> } & AsyncDisposable;
5
18
 
6
19
  export function createDisposable(dispose: () => void, options?: { once?: boolean }): UnifiedDisposable;
@@ -57,7 +70,7 @@ export function disposableInterval(fn: (...args: any[]) => void, ms: number): Un
57
70
  }
58
71
 
59
72
  export function fromDisposables(
60
- ...disposables: (UnifiedDisposable | Disposable | { dispose: () => void } | undefined)[]
73
+ ...disposables: (UnifiedDisposable | globalThis.Disposable | { dispose: () => void } | undefined)[]
61
74
  ): UnifiedDisposable {
62
75
  let disposed = false;
63
76
  const dispose = () => {