@gitkraken/core-gitlens 0.3.0 → 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 (378) hide show
  1. package/CHANGELOG.md +20 -1
  2. package/README.md +13 -10
  3. package/dist/git/cache.d.ts +12 -6
  4. package/dist/git/cache.d.ts.map +1 -1
  5. package/dist/git/cache.js +40 -39
  6. package/dist/git/cache.js.map +1 -1
  7. package/dist/git/context.d.ts +23 -3
  8. package/dist/git/context.d.ts.map +1 -1
  9. package/dist/git/context.js.map +1 -1
  10. package/dist/git/features.d.ts +1 -1
  11. package/dist/git/features.d.ts.map +1 -1
  12. package/dist/git/features.js +1 -0
  13. package/dist/git/features.js.map +1 -1
  14. package/dist/git/models/graph.d.ts +96 -0
  15. package/dist/git/models/graph.d.ts.map +1 -1
  16. package/dist/git/models/graph.js +24 -1
  17. package/dist/git/models/graph.js.map +1 -1
  18. package/dist/git/models/remoteProvider.d.ts +1 -0
  19. package/dist/git/models/remoteProvider.d.ts.map +1 -1
  20. package/dist/git/models/remoteProvider.js.map +1 -1
  21. package/dist/git/models/repository.d.ts +21 -12
  22. package/dist/git/models/repository.d.ts.map +1 -1
  23. package/dist/git/models/repository.js +70 -84
  24. package/dist/git/models/repository.js.map +1 -1
  25. package/dist/git/models/statusFile.d.ts +9 -0
  26. package/dist/git/models/statusFile.d.ts.map +1 -1
  27. package/dist/git/models/statusFile.js +11 -0
  28. package/dist/git/models/statusFile.js.map +1 -1
  29. package/dist/git/providers/commits.d.ts +4 -0
  30. package/dist/git/providers/commits.d.ts.map +1 -1
  31. package/dist/git/providers/config.d.ts +1 -3
  32. package/dist/git/providers/config.d.ts.map +1 -1
  33. package/dist/git/providers/operations.d.ts +40 -13
  34. package/dist/git/providers/operations.d.ts.map +1 -1
  35. package/dist/git/providers/worktrees.d.ts +2 -0
  36. package/dist/git/providers/worktrees.d.ts.map +1 -1
  37. package/dist/git/remotes/custom.d.ts +2 -0
  38. package/dist/git/remotes/custom.d.ts.map +1 -1
  39. package/dist/git/remotes/custom.js +20 -0
  40. package/dist/git/remotes/custom.js.map +1 -1
  41. package/dist/git/utils/conflictResolution.utils.d.ts +32 -0
  42. package/dist/git/utils/conflictResolution.utils.d.ts.map +1 -1
  43. package/dist/git/utils/conflictResolution.utils.js +95 -0
  44. package/dist/git/utils/conflictResolution.utils.js.map +1 -1
  45. package/dist/git/utils/contributor.utils.d.ts +3 -0
  46. package/dist/git/utils/contributor.utils.d.ts.map +1 -1
  47. package/dist/git/utils/contributor.utils.js +22 -0
  48. package/dist/git/utils/contributor.utils.js.map +1 -1
  49. package/dist/git/utils/reachability.utils.d.ts +37 -0
  50. package/dist/git/utils/reachability.utils.d.ts.map +1 -0
  51. package/dist/git/utils/reachability.utils.js +96 -0
  52. package/dist/git/utils/reachability.utils.js.map +1 -0
  53. package/dist/git/watching/watchService.d.ts +4 -2
  54. package/dist/git/watching/watchService.d.ts.map +1 -1
  55. package/dist/git/watching/watchService.js +8 -3
  56. package/dist/git/watching/watchService.js.map +1 -1
  57. package/dist/git/watching/watchSession.d.ts +14 -12
  58. package/dist/git/watching/watchSession.d.ts.map +1 -1
  59. package/dist/git/watching/watchSession.js +56 -55
  60. package/dist/git/watching/watchSession.js.map +1 -1
  61. package/dist/git-cli/providers/branches.d.ts.map +1 -1
  62. package/dist/git-cli/providers/branches.js +1 -0
  63. package/dist/git-cli/providers/branches.js.map +1 -1
  64. package/dist/git-cli/providers/commits.d.ts +1 -0
  65. package/dist/git-cli/providers/commits.d.ts.map +1 -1
  66. package/dist/git-cli/providers/commits.js +12 -0
  67. package/dist/git-cli/providers/commits.js.map +1 -1
  68. package/dist/git-cli/providers/config.d.ts +8 -4
  69. package/dist/git-cli/providers/config.d.ts.map +1 -1
  70. package/dist/git-cli/providers/config.js +62 -39
  71. package/dist/git-cli/providers/config.js.map +1 -1
  72. package/dist/git-cli/providers/diff.d.ts.map +1 -1
  73. package/dist/git-cli/providers/diff.js +1 -1
  74. package/dist/git-cli/providers/diff.js.map +1 -1
  75. package/dist/git-cli/providers/graph.d.ts.map +1 -1
  76. package/dist/git-cli/providers/graph.js +132 -14
  77. package/dist/git-cli/providers/graph.js.map +1 -1
  78. package/dist/git-cli/providers/operations.d.ts +7 -5
  79. package/dist/git-cli/providers/operations.d.ts.map +1 -1
  80. package/dist/git-cli/providers/operations.js +118 -95
  81. package/dist/git-cli/providers/operations.js.map +1 -1
  82. package/dist/git-cli/providers/stash.d.ts.map +1 -1
  83. package/dist/git-cli/providers/stash.js +20 -2
  84. package/dist/git-cli/providers/stash.js.map +1 -1
  85. package/dist/git-cli/providers/status.d.ts.map +1 -1
  86. package/dist/git-cli/providers/status.js +5 -2
  87. package/dist/git-cli/providers/status.js.map +1 -1
  88. package/dist/git-cli/providers/worktrees.d.ts +2 -0
  89. package/dist/git-cli/providers/worktrees.d.ts.map +1 -1
  90. package/dist/git-cli/providers/worktrees.js +3 -0
  91. package/dist/git-cli/providers/worktrees.js.map +1 -1
  92. package/dist/ipc/discovery.d.ts +22 -0
  93. package/dist/ipc/discovery.d.ts.map +1 -1
  94. package/dist/ipc/discovery.js +111 -2
  95. package/dist/ipc/discovery.js.map +1 -1
  96. package/dist/plus/agents/providers/claudeCodeProvider.d.ts +73 -20
  97. package/dist/plus/agents/providers/claudeCodeProvider.d.ts.map +1 -1
  98. package/dist/plus/agents/providers/claudeCodeProvider.js +394 -88
  99. package/dist/plus/agents/providers/claudeCodeProvider.js.map +1 -1
  100. package/dist/plus/agents/types.d.ts +62 -11
  101. package/dist/plus/agents/types.d.ts.map +1 -1
  102. package/dist/plus/ai/models/model.d.ts +1 -1
  103. package/dist/plus/ai/models/model.d.ts.map +1 -1
  104. package/dist/plus/ai/models/model.js.map +1 -1
  105. package/dist/plus/ai/models/provider.d.ts +3 -0
  106. package/dist/plus/ai/models/provider.d.ts.map +1 -1
  107. package/dist/plus/ai/providers/gitkrakenProvider.d.ts +1 -1
  108. package/dist/plus/ai/providers/gitkrakenProvider.d.ts.map +1 -1
  109. package/dist/plus/ai/providers/gitkrakenProvider.js +4 -1
  110. package/dist/plus/ai/providers/gitkrakenProvider.js.map +1 -1
  111. package/dist/plus/ai/providers/openAICompatibleProviderBase.d.ts +4 -3
  112. package/dist/plus/ai/providers/openAICompatibleProviderBase.d.ts.map +1 -1
  113. package/dist/plus/ai/providers/openAICompatibleProviderBase.js +9 -6
  114. package/dist/plus/ai/providers/openAICompatibleProviderBase.js.map +1 -1
  115. package/dist/plus/ai/utils/ai.utils.d.ts.map +1 -1
  116. package/dist/plus/ai/utils/ai.utils.js +6 -4
  117. package/dist/plus/ai/utils/ai.utils.js.map +1 -1
  118. package/dist/plus/git-github/api/github.d.ts +8 -13
  119. package/dist/plus/git-github/api/github.d.ts.map +1 -1
  120. package/dist/plus/git-github/api/github.js +96 -14
  121. package/dist/plus/git-github/api/github.js.map +1 -1
  122. package/dist/plus/git-github/providers/github/refs.js +1 -1
  123. package/dist/plus/integrations/authentication/cloudIntegrationService.d.ts +11 -0
  124. package/dist/plus/integrations/authentication/cloudIntegrationService.d.ts.map +1 -0
  125. package/dist/plus/integrations/authentication/cloudIntegrationService.js +90 -0
  126. package/dist/plus/integrations/authentication/cloudIntegrationService.js.map +1 -0
  127. package/dist/plus/integrations/authentication/configuredIntegrationService.d.ts +67 -0
  128. package/dist/plus/integrations/authentication/configuredIntegrationService.d.ts.map +1 -0
  129. package/dist/plus/integrations/authentication/configuredIntegrationService.js +295 -0
  130. package/dist/plus/integrations/authentication/configuredIntegrationService.js.map +1 -0
  131. package/dist/plus/integrations/authentication/integrationAuthenticationProvider.d.ts +92 -0
  132. package/dist/plus/integrations/authentication/integrationAuthenticationProvider.d.ts.map +1 -0
  133. package/dist/plus/integrations/authentication/integrationAuthenticationProvider.js +185 -0
  134. package/dist/plus/integrations/authentication/integrationAuthenticationProvider.js.map +1 -0
  135. package/dist/plus/integrations/authentication/integrationAuthenticationService.d.ts +62 -0
  136. package/dist/plus/integrations/authentication/integrationAuthenticationService.d.ts.map +1 -0
  137. package/dist/plus/integrations/authentication/integrationAuthenticationService.js +122 -0
  138. package/dist/plus/integrations/authentication/integrationAuthenticationService.js.map +1 -0
  139. package/dist/plus/integrations/authentication/manualTokenProvider.d.ts +15 -0
  140. package/dist/plus/integrations/authentication/manualTokenProvider.d.ts.map +1 -0
  141. package/dist/plus/integrations/authentication/manualTokenProvider.js +49 -0
  142. package/dist/plus/integrations/authentication/manualTokenProvider.js.map +1 -0
  143. package/dist/plus/integrations/authentication/models.d.ts +87 -0
  144. package/dist/plus/integrations/authentication/models.d.ts.map +1 -0
  145. package/dist/plus/integrations/authentication/models.js +64 -0
  146. package/dist/plus/integrations/authentication/models.js.map +1 -0
  147. package/dist/plus/integrations/constants.d.ts +47 -0
  148. package/dist/plus/integrations/constants.d.ts.map +1 -0
  149. package/dist/plus/integrations/constants.js +128 -0
  150. package/dist/plus/integrations/constants.js.map +1 -0
  151. package/dist/plus/integrations/context.d.ts +354 -0
  152. package/dist/plus/integrations/context.d.ts.map +1 -0
  153. package/dist/plus/integrations/context.js +2 -0
  154. package/dist/plus/integrations/context.js.map +1 -0
  155. package/dist/plus/integrations/errors.d.ts +14 -0
  156. package/dist/plus/integrations/errors.d.ts.map +1 -0
  157. package/dist/plus/integrations/errors.js +19 -0
  158. package/dist/plus/integrations/errors.js.map +1 -0
  159. package/dist/plus/integrations/index.d.ts +32 -0
  160. package/dist/plus/integrations/index.d.ts.map +1 -0
  161. package/dist/plus/integrations/index.js +62 -0
  162. package/dist/plus/integrations/index.js.map +1 -0
  163. package/dist/plus/integrations/integrationService.d.ts +98 -0
  164. package/dist/plus/integrations/integrationService.d.ts.map +1 -0
  165. package/dist/plus/integrations/integrationService.js +627 -0
  166. package/dist/plus/integrations/integrationService.js.map +1 -0
  167. package/dist/plus/integrations/models/gitHostIntegration.d.ts +82 -0
  168. package/dist/plus/integrations/models/gitHostIntegration.d.ts.map +1 -0
  169. package/dist/plus/integrations/models/gitHostIntegration.js +522 -0
  170. package/dist/plus/integrations/models/gitHostIntegration.js.map +1 -0
  171. package/dist/plus/integrations/models/integration.d.ts +127 -0
  172. package/dist/plus/integrations/models/integration.d.ts.map +1 -0
  173. package/dist/plus/integrations/models/integration.js +456 -0
  174. package/dist/plus/integrations/models/integration.js.map +1 -0
  175. package/dist/plus/integrations/models/issuesIntegration.d.ts +28 -0
  176. package/dist/plus/integrations/models/issuesIntegration.d.ts.map +1 -0
  177. package/dist/plus/integrations/models/issuesIntegration.js +101 -0
  178. package/dist/plus/integrations/models/issuesIntegration.js.map +1 -0
  179. package/dist/plus/integrations/providers/apiClients.d.ts +25 -0
  180. package/dist/plus/integrations/providers/apiClients.d.ts.map +1 -0
  181. package/dist/plus/integrations/providers/apiClients.js +39 -0
  182. package/dist/plus/integrations/providers/apiClients.js.map +1 -0
  183. package/dist/plus/integrations/providers/azure/azure.d.ts +47 -0
  184. package/dist/plus/integrations/providers/azure/azure.d.ts.map +1 -0
  185. package/dist/plus/integrations/providers/azure/azure.js +444 -0
  186. package/dist/plus/integrations/providers/azure/azure.js.map +1 -0
  187. package/dist/plus/integrations/providers/azure/models.d.ts +286 -0
  188. package/dist/plus/integrations/providers/azure/models.d.ts.map +1 -0
  189. package/dist/plus/integrations/providers/azure/models.js +203 -0
  190. package/dist/plus/integrations/providers/azure/models.js.map +1 -0
  191. package/dist/plus/integrations/providers/azureDevOps.d.ts +95 -0
  192. package/dist/plus/integrations/providers/azureDevOps.d.ts.map +1 -0
  193. package/dist/plus/integrations/providers/azureDevOps.js +432 -0
  194. package/dist/plus/integrations/providers/azureDevOps.js.map +1 -0
  195. package/dist/plus/integrations/providers/bitbucket/bitbucket.d.ts +42 -0
  196. package/dist/plus/integrations/providers/bitbucket/bitbucket.d.ts.map +1 -0
  197. package/dist/plus/integrations/providers/bitbucket/bitbucket.js +513 -0
  198. package/dist/plus/integrations/providers/bitbucket/bitbucket.js.map +1 -0
  199. package/dist/plus/integrations/providers/bitbucket/models.d.ts +222 -0
  200. package/dist/plus/integrations/providers/bitbucket/models.d.ts.map +1 -0
  201. package/dist/plus/integrations/providers/bitbucket/models.js +158 -0
  202. package/dist/plus/integrations/providers/bitbucket/models.js.map +1 -0
  203. package/dist/plus/integrations/providers/bitbucket-server/models.d.ts +120 -0
  204. package/dist/plus/integrations/providers/bitbucket-server/models.d.ts.map +1 -0
  205. package/dist/plus/integrations/providers/bitbucket-server/models.js +111 -0
  206. package/dist/plus/integrations/providers/bitbucket-server/models.js.map +1 -0
  207. package/dist/plus/integrations/providers/bitbucket-server.d.ts +60 -0
  208. package/dist/plus/integrations/providers/bitbucket-server.d.ts.map +1 -0
  209. package/dist/plus/integrations/providers/bitbucket-server.js +138 -0
  210. package/dist/plus/integrations/providers/bitbucket-server.js.map +1 -0
  211. package/dist/plus/integrations/providers/bitbucket.d.ts +50 -0
  212. package/dist/plus/integrations/providers/bitbucket.d.ts.map +1 -0
  213. package/dist/plus/integrations/providers/bitbucket.js +181 -0
  214. package/dist/plus/integrations/providers/bitbucket.js.map +1 -0
  215. package/dist/plus/integrations/providers/github/github.d.ts +5 -0
  216. package/dist/plus/integrations/providers/github/github.d.ts.map +1 -0
  217. package/dist/plus/integrations/providers/github/github.js +47 -0
  218. package/dist/plus/integrations/providers/github/github.js.map +1 -0
  219. package/dist/plus/integrations/providers/github/github.utils.d.ts +11 -0
  220. package/dist/plus/integrations/providers/github/github.utils.d.ts.map +1 -0
  221. package/dist/plus/integrations/providers/github/github.utils.js +6 -0
  222. package/dist/plus/integrations/providers/github/github.utils.js.map +1 -0
  223. package/dist/plus/integrations/providers/github/models.d.ts +3 -0
  224. package/dist/plus/integrations/providers/github/models.d.ts.map +1 -0
  225. package/dist/plus/integrations/providers/github/models.js +2 -0
  226. package/dist/plus/integrations/providers/github/models.js.map +1 -0
  227. package/dist/plus/integrations/providers/github.d.ts +73 -0
  228. package/dist/plus/integrations/providers/github.d.ts.map +1 -0
  229. package/dist/plus/integrations/providers/github.js +160 -0
  230. package/dist/plus/integrations/providers/github.js.map +1 -0
  231. package/dist/plus/integrations/providers/gitlab/gitlab.d.ts +63 -0
  232. package/dist/plus/integrations/providers/gitlab/gitlab.d.ts.map +1 -0
  233. package/dist/plus/integrations/providers/gitlab/gitlab.js +828 -0
  234. package/dist/plus/integrations/providers/gitlab/gitlab.js.map +1 -0
  235. package/dist/plus/integrations/providers/gitlab/gitlab.utils.d.ts +21 -0
  236. package/dist/plus/integrations/providers/gitlab/gitlab.utils.d.ts.map +1 -0
  237. package/dist/plus/integrations/providers/gitlab/gitlab.utils.js +45 -0
  238. package/dist/plus/integrations/providers/gitlab/gitlab.utils.js.map +1 -0
  239. package/dist/plus/integrations/providers/gitlab/models.d.ts +128 -0
  240. package/dist/plus/integrations/providers/gitlab/models.d.ts.map +1 -0
  241. package/dist/plus/integrations/providers/gitlab/models.js +96 -0
  242. package/dist/plus/integrations/providers/gitlab/models.js.map +1 -0
  243. package/dist/plus/integrations/providers/gitlab.d.ts +79 -0
  244. package/dist/plus/integrations/providers/gitlab.d.ts.map +1 -0
  245. package/dist/plus/integrations/providers/gitlab.js +253 -0
  246. package/dist/plus/integrations/providers/gitlab.js.map +1 -0
  247. package/dist/plus/integrations/providers/jira.d.ts +46 -0
  248. package/dist/plus/integrations/providers/jira.d.ts.map +1 -0
  249. package/dist/plus/integrations/providers/jira.js +255 -0
  250. package/dist/plus/integrations/providers/jira.js.map +1 -0
  251. package/dist/plus/integrations/providers/linear.d.ts +47 -0
  252. package/dist/plus/integrations/providers/linear.d.ts.map +1 -0
  253. package/dist/plus/integrations/providers/linear.js +198 -0
  254. package/dist/plus/integrations/providers/linear.js.map +1 -0
  255. package/dist/plus/integrations/providers/models.d.ts +433 -0
  256. package/dist/plus/integrations/providers/models.d.ts.map +1 -0
  257. package/dist/plus/integrations/providers/models.js +602 -0
  258. package/dist/plus/integrations/providers/models.js.map +1 -0
  259. package/dist/plus/integrations/providers/providersApi.d.ts +129 -0
  260. package/dist/plus/integrations/providers/providersApi.d.ts.map +1 -0
  261. package/dist/plus/integrations/providers/providersApi.js +602 -0
  262. package/dist/plus/integrations/providers/providersApi.js.map +1 -0
  263. package/dist/plus/integrations/providers/utils.d.ts +54 -0
  264. package/dist/plus/integrations/providers/utils.d.ts.map +1 -0
  265. package/dist/plus/integrations/providers/utils.js +262 -0
  266. package/dist/plus/integrations/providers/utils.js.map +1 -0
  267. package/dist/plus/integrations/telemetry.d.ts +26 -0
  268. package/dist/plus/integrations/telemetry.d.ts.map +1 -0
  269. package/dist/plus/integrations/telemetry.js +11 -0
  270. package/dist/plus/integrations/telemetry.js.map +1 -0
  271. package/dist/plus/integrations/utils/integration.utils.d.ts +14 -0
  272. package/dist/plus/integrations/utils/integration.utils.d.ts.map +1 -0
  273. package/dist/plus/integrations/utils/integration.utils.js +111 -0
  274. package/dist/plus/integrations/utils/integration.utils.js.map +1 -0
  275. package/dist/utils/date.d.ts.map +1 -1
  276. package/dist/utils/date.js +6 -0
  277. package/dist/utils/date.js.map +1 -1
  278. package/dist/utils/debounce.js +1 -1
  279. package/dist/utils/disposable.d.ts +15 -2
  280. package/dist/utils/disposable.d.ts.map +1 -1
  281. package/dist/utils/disposable.js.map +1 -1
  282. package/dist/utils/iterable.d.ts +7 -1
  283. package/dist/utils/iterable.d.ts.map +1 -1
  284. package/dist/utils/iterable.js +12 -4
  285. package/dist/utils/iterable.js.map +1 -1
  286. package/dist/utils/object.d.ts +22 -1
  287. package/dist/utils/object.d.ts.map +1 -1
  288. package/dist/utils/object.js +56 -3
  289. package/dist/utils/object.js.map +1 -1
  290. package/dist/utils/paging.js +14 -15
  291. package/dist/utils/paging.js.map +1 -1
  292. package/dist/utils/promiseCache.d.ts.map +1 -1
  293. package/dist/utils/promiseCache.js +12 -4
  294. package/dist/utils/promiseCache.js.map +1 -1
  295. package/dist/utils/string.js +1 -1
  296. package/package.json +43 -2
  297. package/src/git/cache.ts +58 -70
  298. package/src/git/context.ts +25 -3
  299. package/src/git/features.ts +2 -0
  300. package/src/git/models/graph.ts +97 -0
  301. package/src/git/models/remoteProvider.ts +1 -0
  302. package/src/git/models/repository.ts +84 -93
  303. package/src/git/models/statusFile.ts +12 -0
  304. package/src/git/providers/commits.ts +4 -0
  305. package/src/git/providers/config.ts +1 -5
  306. package/src/git/providers/operations.ts +42 -22
  307. package/src/git/providers/worktrees.ts +14 -2
  308. package/src/git/remotes/custom.ts +23 -0
  309. package/src/git/utils/conflictResolution.utils.ts +126 -0
  310. package/src/git/utils/contributor.utils.ts +24 -0
  311. package/src/git/utils/reachability.utils.ts +109 -0
  312. package/src/git/watching/watchService.ts +9 -4
  313. package/src/git/watching/watchSession.ts +61 -55
  314. package/src/git-cli/providers/branches.ts +1 -0
  315. package/src/git-cli/providers/commits.ts +24 -0
  316. package/src/git-cli/providers/config.ts +63 -49
  317. package/src/git-cli/providers/diff.ts +2 -1
  318. package/src/git-cli/providers/graph.ts +145 -14
  319. package/src/git-cli/providers/operations.ts +138 -130
  320. package/src/git-cli/providers/stash.ts +20 -2
  321. package/src/git-cli/providers/status.ts +11 -3
  322. package/src/git-cli/providers/worktrees.ts +17 -2
  323. package/src/ipc/discovery.ts +132 -2
  324. package/src/plus/agents/providers/claudeCodeProvider.ts +430 -90
  325. package/src/plus/agents/types.ts +59 -11
  326. package/src/plus/ai/models/model.ts +1 -0
  327. package/src/plus/ai/models/provider.ts +7 -1
  328. package/src/plus/ai/providers/gitkrakenProvider.ts +4 -0
  329. package/src/plus/ai/providers/openAICompatibleProviderBase.ts +21 -4
  330. package/src/plus/ai/utils/ai.utils.ts +6 -4
  331. package/src/plus/git-github/api/github.ts +131 -31
  332. package/src/plus/git-github/providers/github/refs.ts +1 -1
  333. package/src/plus/integrations/authentication/cloudIntegrationService.ts +120 -0
  334. package/src/plus/integrations/authentication/configuredIntegrationService.ts +414 -0
  335. package/src/plus/integrations/authentication/integrationAuthenticationProvider.ts +289 -0
  336. package/src/plus/integrations/authentication/integrationAuthenticationService.ts +144 -0
  337. package/src/plus/integrations/authentication/manualTokenProvider.ts +72 -0
  338. package/src/plus/integrations/authentication/models.ts +168 -0
  339. package/src/plus/integrations/constants.ts +169 -0
  340. package/src/plus/integrations/context.ts +383 -0
  341. package/src/plus/integrations/errors.ts +35 -0
  342. package/src/plus/integrations/index.ts +119 -0
  343. package/src/plus/integrations/integrationService.ts +924 -0
  344. package/src/plus/integrations/models/gitHostIntegration.ts +738 -0
  345. package/src/plus/integrations/models/integration.ts +657 -0
  346. package/src/plus/integrations/models/issuesIntegration.ts +124 -0
  347. package/src/plus/integrations/providers/apiClients.ts +72 -0
  348. package/src/plus/integrations/providers/azure/azure.ts +691 -0
  349. package/src/plus/integrations/providers/azure/models.ts +605 -0
  350. package/src/plus/integrations/providers/azureDevOps.ts +677 -0
  351. package/src/plus/integrations/providers/bitbucket/bitbucket.ts +774 -0
  352. package/src/plus/integrations/providers/bitbucket/models.ts +445 -0
  353. package/src/plus/integrations/providers/bitbucket-server/models.ts +252 -0
  354. package/src/plus/integrations/providers/bitbucket-server.ts +282 -0
  355. package/src/plus/integrations/providers/bitbucket.ts +350 -0
  356. package/src/plus/integrations/providers/github/github.ts +64 -0
  357. package/src/plus/integrations/providers/github/github.utils.ts +23 -0
  358. package/src/plus/integrations/providers/github/models.ts +29 -0
  359. package/src/plus/integrations/providers/github.ts +366 -0
  360. package/src/plus/integrations/providers/gitlab/gitlab.ts +1210 -0
  361. package/src/plus/integrations/providers/gitlab/gitlab.utils.ts +71 -0
  362. package/src/plus/integrations/providers/gitlab/models.ts +257 -0
  363. package/src/plus/integrations/providers/gitlab.ts +473 -0
  364. package/src/plus/integrations/providers/jira.ts +359 -0
  365. package/src/plus/integrations/providers/linear.ts +275 -0
  366. package/src/plus/integrations/providers/models.ts +1114 -0
  367. package/src/plus/integrations/providers/providersApi.ts +1126 -0
  368. package/src/plus/integrations/providers/utils.ts +359 -0
  369. package/src/plus/integrations/telemetry.ts +29 -0
  370. package/src/plus/integrations/utils/integration.utils.ts +138 -0
  371. package/src/utils/date.ts +5 -0
  372. package/src/utils/debounce.ts +1 -1
  373. package/src/utils/disposable.ts +15 -2
  374. package/src/utils/iterable.ts +14 -3
  375. package/src/utils/object.ts +55 -4
  376. package/src/utils/paging.ts +14 -14
  377. package/src/utils/promiseCache.ts +24 -16
  378. package/src/utils/string.ts +1 -1
@@ -0,0 +1,677 @@
1
+ import type { Account, UnidentifiedAuthor } from '../../../git/models/author.js';
2
+ import type { DefaultBranch } from '../../../git/models/defaultBranch.js';
3
+ import type { Issue, IssueShape } from '../../../git/models/issue.js';
4
+ import type { IssueOrPullRequest, IssueOrPullRequestType } from '../../../git/models/issueOrPullRequest.js';
5
+ import type { PullRequest, PullRequestMergeMethod, PullRequestState } from '../../../git/models/pullRequest.js';
6
+ import type { RepositoryMetadata } from '../../../git/models/repositoryMetadata.js';
7
+ import { base64 } from '../../../utils/base64.js';
8
+ import type { Emitter } from '../../../utils/event.js';
9
+ import { flatSettled } from '../../../utils/promise.js';
10
+ import type { IntegrationAuthenticationProviderDescriptor } from '../authentication/integrationAuthenticationProvider.js';
11
+ import type { IntegrationAuthenticationService } from '../authentication/integrationAuthenticationService.js';
12
+ import type { IntegrationServiceContext } from '../context.js';
13
+ import type {
14
+ AuthenticationSessionLike as AuthenticationSession,
15
+ ProviderAuthenticationSession,
16
+ TokenWithInfo,
17
+ } from '../authentication/models.js';
18
+ import { toTokenWithInfo } from '../authentication/models.js';
19
+ import { GitCloudHostIntegrationId, GitSelfManagedHostIntegrationId } from '../constants.js';
20
+ import type { IntegrationConnectionChangeEvent } from '../integrationService.js';
21
+ import { GitHostIntegration } from '../models/gitHostIntegration.js';
22
+ import type { IntegrationKey } from '../models/integration.js';
23
+ import type {
24
+ AzureOrganizationDescriptor,
25
+ AzureProjectDescriptor,
26
+ AzureProjectInputDescriptor,
27
+ AzureRemoteRepositoryDescriptor,
28
+ AzureRepositoryDescriptor,
29
+ } from './azure/models.js';
30
+ import type { ProviderPullRequest, ProviderRepository } from './models.js';
31
+ import { fromProviderIssue, fromProviderPullRequest, providersMetadata } from './models.js';
32
+ import type { ProvidersApi } from './providersApi.js';
33
+
34
+ export abstract class AzureDevOpsIntegrationBase<
35
+ TIntegrationId extends GitCloudHostIntegrationId.AzureDevOps | GitSelfManagedHostIntegrationId.AzureDevOpsServer,
36
+ TRepositoryDescriptor extends AzureRepositoryDescriptor = AzureRepositoryDescriptor,
37
+ > extends GitHostIntegration<TIntegrationId, TRepositoryDescriptor> {
38
+ protected abstract get apiBaseUrl(): string;
39
+ protected getApiOptions(
40
+ session: ProviderAuthenticationSession,
41
+ doNotConvertToPat: boolean = false,
42
+ ): {
43
+ tokenWithInfo: TokenWithInfo<TIntegrationId>;
44
+ options: { isPAT: boolean; baseUrl?: string };
45
+ } {
46
+ const usePat = !doNotConvertToPat;
47
+ const accessToken = usePat ? convertTokentoPAT(session.accessToken) : session.accessToken;
48
+ const tokenWithInfo = toTokenWithInfo<TIntegrationId>(this.id, session, accessToken);
49
+ return {
50
+ tokenWithInfo: tokenWithInfo,
51
+ options: { isPAT: usePat },
52
+ };
53
+ }
54
+
55
+ private _accounts: Map<string, Account | undefined> | undefined;
56
+ protected override async getProviderCurrentAccount(
57
+ session: ProviderAuthenticationSession,
58
+ ): Promise<Account | undefined> {
59
+ const { accessToken } = session;
60
+ this._accounts ??= new Map<string, Account | undefined>();
61
+
62
+ const cachedAccount = this._accounts.get(accessToken);
63
+ if (cachedAccount == null) {
64
+ const user = await this._requestForCurrentUser(session);
65
+ this._accounts.set(accessToken, user);
66
+ }
67
+
68
+ return this._accounts.get(accessToken);
69
+ }
70
+
71
+ protected async _requestForCurrentUser(session: ProviderAuthenticationSession): Promise<Account | undefined> {
72
+ const api = await this.getProvidersApi();
73
+ const { tokenWithInfo, options } = this.getApiOptions(session, true);
74
+ const user = await api.getCurrentUser(tokenWithInfo, options);
75
+ return user
76
+ ? {
77
+ provider: this,
78
+ id: user.id,
79
+ name: user.name ?? undefined,
80
+ email: user.email ?? undefined,
81
+ avatarUrl: user.avatarUrl ?? undefined,
82
+ username: user.username ?? undefined,
83
+ }
84
+ : undefined;
85
+ }
86
+
87
+ private _organizations: Map<string, AzureOrganizationDescriptor[] | undefined> | undefined;
88
+ private async getProviderResourcesForUser(
89
+ session: ProviderAuthenticationSession,
90
+ force: boolean = false,
91
+ ): Promise<AzureOrganizationDescriptor[] | undefined> {
92
+ this._organizations ??= new Map<string, AzureOrganizationDescriptor[] | undefined>();
93
+ const { accessToken } = session;
94
+ const cachedResources = this._organizations.get(accessToken);
95
+
96
+ if (cachedResources == null || force) {
97
+ const api = await this.getProvidersApi();
98
+ const account = await this.getProviderCurrentAccount(session);
99
+ if (account?.id == null) return undefined;
100
+
101
+ const { tokenWithInfo, options } = this.getApiOptions(session);
102
+ const resources = await api.getAzureResourcesForUser(tokenWithInfo, account.id, options);
103
+ this._organizations.set(
104
+ accessToken,
105
+ resources != null ? resources.map(r => ({ ...r, key: r.id })) : undefined,
106
+ );
107
+ }
108
+
109
+ return this._organizations.get(accessToken);
110
+ }
111
+
112
+ private _projects: Map<string, AzureProjectDescriptor[] | undefined> | undefined;
113
+ private async getProviderProjectsForResources(
114
+ session: ProviderAuthenticationSession,
115
+ resources: AzureOrganizationDescriptor[],
116
+ force: boolean = false,
117
+ ): Promise<AzureProjectDescriptor[] | undefined> {
118
+ this._projects ??= new Map<string, AzureProjectDescriptor[] | undefined>();
119
+ const { accessToken } = session;
120
+
121
+ let resourcesWithoutProjects = [];
122
+ if (force) {
123
+ resourcesWithoutProjects = resources;
124
+ } else {
125
+ for (const resource of resources) {
126
+ const resourceKey = `${accessToken}:${resource.id}`;
127
+ const cachedProjects = this._projects.get(resourceKey);
128
+ if (cachedProjects == null) {
129
+ resourcesWithoutProjects.push(resource);
130
+ }
131
+ }
132
+ }
133
+
134
+ if (resourcesWithoutProjects.length > 0) {
135
+ const api = await this.getProvidersApi();
136
+ const { tokenWithInfo, options } = this.getApiOptions(session);
137
+ const azureProjects = await flatSettled(
138
+ resourcesWithoutProjects.map(
139
+ async resource =>
140
+ (await api.getAzureProjectsForResource(tokenWithInfo, resource.name, options)).values,
141
+ ),
142
+ );
143
+
144
+ for (const resource of resourcesWithoutProjects) {
145
+ const projects = azureProjects?.filter(p => p.namespace === resource.name);
146
+ if (projects != null) {
147
+ this._projects.set(
148
+ `${accessToken}:${resource.id}`,
149
+ projects.map(p => ({
150
+ id: p.id,
151
+ name: p.name,
152
+ resourceId: resource.id,
153
+ resourceName: resource.name,
154
+ key: p.id,
155
+ })),
156
+ );
157
+ }
158
+ }
159
+ }
160
+
161
+ return resources.reduce<AzureProjectDescriptor[]>((projects, resource) => {
162
+ const resourceProjects = this._projects!.get(`${accessToken}:${resource.id}`);
163
+ if (resourceProjects != null) {
164
+ projects.push(...resourceProjects);
165
+ }
166
+ return projects;
167
+ }, []);
168
+ }
169
+
170
+ private async getRepoDescriptorsForProjects(
171
+ session: ProviderAuthenticationSession,
172
+ projects: AzureProjectDescriptor[],
173
+ ): Promise<Map<string, AzureRemoteRepositoryDescriptor[] | undefined>> {
174
+ const descriptors = new Map<string, AzureRemoteRepositoryDescriptor[] | undefined>();
175
+ if (projects.length === 0) return descriptors;
176
+
177
+ const api = await this.getProvidersApi();
178
+ const { tokenWithInfo, options } = this.getApiOptions(session);
179
+ await Promise.all(
180
+ projects.map(async project => {
181
+ const repos = (
182
+ await api.getReposForAzureProject(tokenWithInfo, project.resourceName, project.name, options)
183
+ )?.values;
184
+ if (repos != null && repos.length > 0) {
185
+ descriptors.set(
186
+ project.id,
187
+ repos.map(r => ({
188
+ id: r.id,
189
+ nodeId: r.graphQLId ?? undefined,
190
+ resourceName: project.resourceName,
191
+ name: r.name,
192
+ projectName: project.name,
193
+ url: r.webUrl ?? undefined,
194
+ cloneUrlHttps: r.httpsUrl ?? undefined,
195
+ cloneUrlSsh: r.sshUrl ?? undefined,
196
+ key: r.id,
197
+ })),
198
+ );
199
+ }
200
+ }),
201
+ );
202
+
203
+ return descriptors;
204
+ }
205
+
206
+ protected override async mergeProviderPullRequest(
207
+ session: ProviderAuthenticationSession,
208
+ pr: PullRequest,
209
+ options?: {
210
+ mergeMethod?: PullRequestMergeMethod;
211
+ },
212
+ ): Promise<boolean> {
213
+ const api = await this.getProvidersApi();
214
+ if (pr.refs == null || pr.project == null) return false;
215
+
216
+ const { tokenWithInfo, options: apiOptions } = this.getApiOptions(session);
217
+
218
+ try {
219
+ const merged = await api.mergePullRequest(tokenWithInfo, pr, {
220
+ ...options,
221
+ ...apiOptions,
222
+ });
223
+ return merged;
224
+ } catch (ex) {
225
+ this.showMergeErrorMessage(ex);
226
+ return false;
227
+ }
228
+ }
229
+
230
+ protected showMergeErrorMessage(ex: Error): void {
231
+ this.ctx.hooks?.ui?.onError?.(
232
+ `${ex.message}. Check branch policies, and ensure you have the necessary permissions to merge the pull request.`,
233
+ );
234
+ }
235
+
236
+ protected override async getProviderAccountForCommit(
237
+ session: ProviderAuthenticationSession,
238
+ repo: AzureRepositoryDescriptor,
239
+ rev: string,
240
+ options?: {
241
+ avatarSize?: number;
242
+ },
243
+ ): Promise<UnidentifiedAuthor | undefined> {
244
+ return (await this.authenticationService.apis.azure)?.getAccountForCommit(
245
+ this,
246
+ toTokenWithInfo(this.id, session),
247
+ repo.owner,
248
+ repo.name,
249
+ rev,
250
+ this.apiBaseUrl,
251
+ options,
252
+ );
253
+ }
254
+
255
+ protected override async getProviderAccountForEmail(
256
+ _session: AuthenticationSession,
257
+ _repo: AzureRepositoryDescriptor,
258
+ _email: string,
259
+ _options?: {
260
+ avatarSize?: number;
261
+ },
262
+ ): Promise<Account | undefined> {
263
+ return Promise.resolve(undefined);
264
+ }
265
+
266
+ protected override async getProviderDefaultBranch(
267
+ _session: AuthenticationSession,
268
+ _repo: AzureRepositoryDescriptor,
269
+ ): Promise<DefaultBranch | undefined> {
270
+ return Promise.resolve(undefined);
271
+ }
272
+
273
+ protected override async getProviderLinkedIssueOrPullRequest(
274
+ session: ProviderAuthenticationSession,
275
+ repo: AzureRepositoryDescriptor,
276
+ { id }: { id: string; key: string },
277
+ type: undefined | IssueOrPullRequestType,
278
+ ): Promise<IssueOrPullRequest | undefined> {
279
+ return (await this.authenticationService.apis.azure)?.getIssueOrPullRequest(
280
+ this,
281
+ toTokenWithInfo(this.id, session),
282
+ repo.owner,
283
+ repo.name,
284
+ id,
285
+ {
286
+ baseUrl: this.apiBaseUrl,
287
+ type: type,
288
+ },
289
+ );
290
+ }
291
+
292
+ protected override async getProviderIssue(
293
+ session: ProviderAuthenticationSession,
294
+ project: AzureProjectInputDescriptor,
295
+ id: string,
296
+ ): Promise<Issue | undefined> {
297
+ const user = await this.getProviderCurrentAccount(session);
298
+ if (user?.username == null) return undefined;
299
+
300
+ const orgs = await this.getProviderResourcesForUser(session);
301
+ if (orgs == null || orgs.length === 0) return undefined;
302
+
303
+ const projects = await this.getProviderProjectsForResources(session, orgs);
304
+ if (projects == null || projects.length === 0) return undefined;
305
+
306
+ const matchingProject = projects.find(p => p.resourceName === project.owner && p.name === project.name);
307
+ if (matchingProject == null) return undefined;
308
+
309
+ return (await this.authenticationService.apis.azure)?.getIssue(
310
+ this,
311
+ toTokenWithInfo(this.id, session),
312
+ matchingProject,
313
+ id,
314
+ {
315
+ baseUrl: this.apiBaseUrl,
316
+ },
317
+ );
318
+ }
319
+
320
+ protected override async getProviderPullRequestForBranch(
321
+ session: ProviderAuthenticationSession,
322
+ repo: AzureRepositoryDescriptor,
323
+ branch: string,
324
+ _options?: {
325
+ avatarSize?: number;
326
+ include?: PullRequestState[];
327
+ },
328
+ ): Promise<PullRequest | undefined> {
329
+ return (await this.authenticationService.apis.azure)?.getPullRequestForBranch(
330
+ this,
331
+ toTokenWithInfo(this.id, session),
332
+ repo.owner,
333
+ repo.name,
334
+ branch,
335
+ {
336
+ baseUrl: this.apiBaseUrl,
337
+ },
338
+ );
339
+ }
340
+
341
+ protected override async getProviderPullRequestForCommit(
342
+ session: ProviderAuthenticationSession,
343
+ repo: AzureRepositoryDescriptor,
344
+ rev: string,
345
+ ): Promise<PullRequest | undefined> {
346
+ return (await this.authenticationService.apis.azure)?.getPullRequestForCommit(
347
+ this,
348
+ toTokenWithInfo(this.id, session),
349
+ repo.owner,
350
+ repo.name,
351
+ rev,
352
+ this.apiBaseUrl,
353
+ );
354
+ }
355
+
356
+ public override async getRepoInfo(repo: {
357
+ owner: string;
358
+ name: string;
359
+ project: string;
360
+ }): Promise<ProviderRepository | undefined> {
361
+ const api = await this.getProvidersApi();
362
+ if (this._session == null) return undefined;
363
+
364
+ const { tokenWithInfo, options } = this.getApiOptions(this._session);
365
+ return api.getRepo(tokenWithInfo, repo.owner, repo.name, repo.project, options);
366
+ }
367
+
368
+ protected override async getProviderRepositoryMetadata(
369
+ _session: AuthenticationSession,
370
+ _repo: AzureRepositoryDescriptor,
371
+ _cancellation?: AbortSignal,
372
+ ): Promise<RepositoryMetadata | undefined> {
373
+ return Promise.resolve(undefined);
374
+ }
375
+
376
+ protected override async searchProviderMyPullRequests(
377
+ session: ProviderAuthenticationSession,
378
+ repos?: AzureRepositoryDescriptor[],
379
+ ): Promise<PullRequest[] | undefined> {
380
+ const api = await this.getProvidersApi();
381
+ if (repos != null) {
382
+ // TODO: implement repos version
383
+ return undefined;
384
+ }
385
+
386
+ const user = await this.getProviderCurrentAccount(session);
387
+ if (user?.username == null) return undefined;
388
+
389
+ const orgs = await this.getProviderResourcesForUser(session);
390
+ if (orgs == null || orgs.length === 0) return undefined;
391
+
392
+ const projects = await this.getProviderProjectsForResources(session, orgs);
393
+ if (projects == null || projects.length === 0) return undefined;
394
+
395
+ const repoDescriptors = [
396
+ ...((await this.getRepoDescriptorsForProjects(session, projects)) ?? new Map()).values(),
397
+ ]
398
+ .filter(r => r != null)
399
+ .flat();
400
+
401
+ const { tokenWithInfo, options } = this.getApiOptions(session);
402
+ const projectInputs = projects.map(p => ({ namespace: p.resourceName, project: p.name }));
403
+ const assignedPrs = (
404
+ await api.getPullRequestsForAzureProjects(tokenWithInfo, projectInputs, {
405
+ ...options,
406
+ assigneeLogins: [user.username],
407
+ })
408
+ )?.map(pr => this.fromAzureProviderPullRequest(pr, repoDescriptors, projects));
409
+ const authoredPrs = (
410
+ await api.getPullRequestsForAzureProjects(tokenWithInfo, projectInputs, {
411
+ ...options,
412
+ authorLogin: user.username,
413
+ })
414
+ )?.map(pr => this.fromAzureProviderPullRequest(pr, repoDescriptors, projects));
415
+ const prsById = new Map<string, PullRequest>();
416
+ for (const pr of authoredPrs ?? []) {
417
+ prsById.set(pr.id, pr);
418
+ }
419
+
420
+ for (const pr of assignedPrs ?? []) {
421
+ const existing = prsById.get(pr.id);
422
+ if (existing == null) {
423
+ prsById.set(pr.id, pr);
424
+ }
425
+ }
426
+
427
+ return [...prsById.values()];
428
+ }
429
+
430
+ protected override async searchProviderMyIssues(
431
+ session: ProviderAuthenticationSession,
432
+ _repos?: AzureRepositoryDescriptor[],
433
+ ): Promise<IssueShape[] | undefined> {
434
+ const api = await this.getProvidersApi();
435
+
436
+ const user = await this.getProviderCurrentAccount(session);
437
+ if (user?.username == null) return undefined;
438
+
439
+ const orgs = await this.getProviderResourcesForUser(session);
440
+ if (orgs == null || orgs.length === 0) return undefined;
441
+
442
+ const projects = await this.getProviderProjectsForResources(session, orgs);
443
+ if (projects == null || projects.length === 0) return undefined;
444
+
445
+ const { tokenWithInfo, options } = this.getApiOptions(session);
446
+ const assignedIssues = await flatSettled(
447
+ projects.map(async p => {
448
+ const issuesResponse = (
449
+ await api.getIssuesForAzureProject(tokenWithInfo, p.resourceName, p.name, {
450
+ ...options,
451
+ assigneeLogins: [user.username!],
452
+ })
453
+ ).values;
454
+ return issuesResponse.map(i => fromProviderIssue(i, this as any, { project: p }));
455
+ }),
456
+ );
457
+ const authoredIssues = await flatSettled(
458
+ projects.map(async p => {
459
+ const issuesResponse = (
460
+ await api.getIssuesForAzureProject(tokenWithInfo, p.resourceName, p.name, {
461
+ ...options,
462
+ authorLogin: user.username!,
463
+ })
464
+ ).values;
465
+ return issuesResponse.map(i => fromProviderIssue(i, this as any, { project: p }));
466
+ }),
467
+ );
468
+ // TODO: Add mentioned issues
469
+ const issuesById = new Map<string, IssueShape>();
470
+
471
+ for (const issue of authoredIssues ?? []) {
472
+ issuesById.set(issue.id, issue);
473
+ }
474
+
475
+ for (const issue of assignedIssues ?? []) {
476
+ const existing = issuesById.get(issue.id);
477
+ if (existing == null) {
478
+ issuesById.set(issue.id, issue);
479
+ }
480
+ }
481
+
482
+ return [...issuesById.values()];
483
+ }
484
+
485
+ protected override async providerOnConnect(): Promise<void> {
486
+ if (this._session == null) return;
487
+
488
+ const storedAccount = this.ctx.storage.get(`azure:${this._session.accessToken}:account`);
489
+ const storedOrganizations = this.ctx.storage.get(`azure:${this._session.accessToken}:organizations`);
490
+ const storedProjects = this.ctx.storage.get(`azure:${this._session.accessToken}:projects`);
491
+ let account: Account | undefined = storedAccount?.data ? { ...storedAccount.data, provider: this } : undefined;
492
+
493
+ let organizations = storedOrganizations?.data?.map((o: AzureOrganizationDescriptor) => ({ ...o }));
494
+
495
+ let projects = storedProjects?.data?.map((p: AzureProjectDescriptor) => ({ ...p }));
496
+
497
+ if (storedAccount == null) {
498
+ account = await this.getProviderCurrentAccount(this._session);
499
+ if (account != null) {
500
+ // Clear all other stored organizations and projects and accounts when our session changes
501
+ await this.ctx.storage.deleteWithPrefix('azure');
502
+ await this.ctx.storage.store(`azure:${this._session.accessToken}:account`, {
503
+ v: 1,
504
+ timestamp: Date.now(),
505
+ data: {
506
+ id: account.id,
507
+ name: account.name,
508
+ email: account.email,
509
+ avatarUrl: account.avatarUrl,
510
+ username: account.username,
511
+ },
512
+ });
513
+ }
514
+ }
515
+
516
+ this._accounts ??= new Map<string, Account | undefined>();
517
+ this._accounts.set(this._session.accessToken, account);
518
+
519
+ if (storedOrganizations == null) {
520
+ organizations = await this.getProviderResourcesForUser(this._session, true);
521
+ await this.ctx.storage.store(`azure:${this._session.accessToken}:organizations`, {
522
+ v: 1,
523
+ timestamp: Date.now(),
524
+ data: organizations,
525
+ });
526
+ }
527
+
528
+ this._organizations ??= new Map<string, AzureOrganizationDescriptor[] | undefined>();
529
+ this._organizations.set(this._session.accessToken, organizations);
530
+
531
+ if (storedProjects == null && organizations?.length) {
532
+ projects = await this.getProviderProjectsForResources(this._session, organizations);
533
+ await this.ctx.storage.store(`azure:${this._session.accessToken}:projects`, {
534
+ v: 1,
535
+ timestamp: Date.now(),
536
+ data: projects,
537
+ });
538
+ }
539
+
540
+ this._projects ??= new Map<string, AzureProjectDescriptor[] | undefined>();
541
+ for (const project of projects ?? []) {
542
+ const projectKey = `${this._session.accessToken}:${project.resourceId}`;
543
+ const projects = this._projects.get(projectKey);
544
+ if (projects == null) {
545
+ this._projects.set(projectKey, [project]);
546
+ } else if (!projects.some(p => p.id === project.id)) {
547
+ projects.push(project);
548
+ }
549
+ }
550
+ }
551
+
552
+ protected override providerOnDisconnect(): void {
553
+ this._organizations = undefined;
554
+ this._projects = undefined;
555
+ this._accounts = undefined;
556
+ }
557
+
558
+ protected fromAzureProviderPullRequest(
559
+ azurePullRequest: ProviderPullRequest,
560
+ repoDescriptors: AzureRemoteRepositoryDescriptor[],
561
+ projectDescriptors: AzureProjectDescriptor[],
562
+ ): PullRequest {
563
+ const baseRepoDescriptor = repoDescriptors.find(r => r.name === azurePullRequest.repository.name);
564
+ const headRepoDescriptor =
565
+ azurePullRequest.headRepository != null
566
+ ? repoDescriptors.find(r => r.name === azurePullRequest.headRepository!.name)
567
+ : undefined;
568
+ let project: AzureProjectDescriptor | undefined;
569
+ if (baseRepoDescriptor != null) {
570
+ azurePullRequest.repository.remoteInfo = {
571
+ ...azurePullRequest.repository.remoteInfo,
572
+ cloneUrlHTTPS: baseRepoDescriptor.cloneUrlHttps ?? '',
573
+ cloneUrlSSH: baseRepoDescriptor.cloneUrlSsh ?? '',
574
+ };
575
+ }
576
+
577
+ if (headRepoDescriptor != null) {
578
+ azurePullRequest.headRepository = {
579
+ ...azurePullRequest.headRepository,
580
+ id: azurePullRequest.headRepository?.id ?? headRepoDescriptor.id,
581
+ name: azurePullRequest.headRepository?.name ?? headRepoDescriptor.name,
582
+ owner: {
583
+ login: azurePullRequest.headRepository?.owner.login ?? headRepoDescriptor.resourceName,
584
+ },
585
+ remoteInfo: {
586
+ ...azurePullRequest.headRepository?.remoteInfo,
587
+ cloneUrlHTTPS: headRepoDescriptor.cloneUrlHttps ?? '',
588
+ cloneUrlSSH: headRepoDescriptor.cloneUrlSsh ?? '',
589
+ },
590
+ };
591
+ }
592
+
593
+ if (baseRepoDescriptor?.projectName != null) {
594
+ project = projectDescriptors.find(p => p.name === baseRepoDescriptor.projectName);
595
+ }
596
+ return fromProviderPullRequest(azurePullRequest, this, { project: project });
597
+ }
598
+ }
599
+
600
+ const cloudMetadata = providersMetadata[GitCloudHostIntegrationId.AzureDevOps];
601
+ const cloudAuthProvider = Object.freeze({ id: cloudMetadata.id, scopes: cloudMetadata.scopes });
602
+
603
+ export class AzureDevOpsIntegration extends AzureDevOpsIntegrationBase<GitCloudHostIntegrationId.AzureDevOps> {
604
+ readonly authProvider: IntegrationAuthenticationProviderDescriptor = cloudAuthProvider;
605
+ readonly id = GitCloudHostIntegrationId.AzureDevOps;
606
+ protected readonly key = this.id;
607
+ readonly name: string = 'Azure DevOps';
608
+ get domain(): string {
609
+ return cloudMetadata.domain;
610
+ }
611
+ protected override get apiBaseUrl(): string {
612
+ return 'https://dev.azure.com';
613
+ }
614
+ }
615
+
616
+ const serverMetadata = providersMetadata[GitSelfManagedHostIntegrationId.AzureDevOpsServer];
617
+ const serverAuthProvider = Object.freeze({ id: serverMetadata.id, scopes: serverMetadata.scopes });
618
+
619
+ export class AzureDevOpsServerIntegration extends AzureDevOpsIntegrationBase<GitSelfManagedHostIntegrationId.AzureDevOpsServer> {
620
+ readonly authProvider: IntegrationAuthenticationProviderDescriptor = serverAuthProvider;
621
+ readonly id = GitSelfManagedHostIntegrationId.AzureDevOpsServer;
622
+ protected readonly key: IntegrationKey<GitSelfManagedHostIntegrationId.AzureDevOpsServer>;
623
+ readonly name: string = 'Azure DevOps Server';
624
+
625
+ constructor(
626
+ ctx: IntegrationServiceContext,
627
+ authenticationService: IntegrationAuthenticationService,
628
+ getProvidersApi: () => Promise<ProvidersApi>,
629
+ didChangeConnection: Emitter<IntegrationConnectionChangeEvent>,
630
+ readonly domain: string,
631
+ ) {
632
+ super(ctx, authenticationService, getProvidersApi, didChangeConnection);
633
+ this.key = `${this.id}:${this.domain}`;
634
+ }
635
+
636
+ protected override get apiBaseUrl(): string {
637
+ const protocol = this._session?.protocol ?? 'https:';
638
+ return `${protocol}//${this.domain}`;
639
+ }
640
+
641
+ protected override getApiOptions(
642
+ session: ProviderAuthenticationSession,
643
+ doNotConvertToPat: boolean = false,
644
+ ): {
645
+ tokenWithInfo: TokenWithInfo<GitSelfManagedHostIntegrationId.AzureDevOpsServer>;
646
+ options: { isPAT: boolean; baseUrl?: string };
647
+ } {
648
+ const { options, ...rest } = super.getApiOptions(session, doNotConvertToPat);
649
+ return {
650
+ ...rest,
651
+ options: { ...options, baseUrl: this.apiBaseUrl },
652
+ };
653
+ }
654
+
655
+ protected override async _requestForCurrentUser(
656
+ session: ProviderAuthenticationSession,
657
+ ): Promise<Account | undefined> {
658
+ const azure = await this.authenticationService.apis.azure;
659
+ const user = azure
660
+ ? await azure.getCurrentUserOnServer(this, toTokenWithInfo(this.id, session), this.apiBaseUrl)
661
+ : undefined;
662
+ return user
663
+ ? {
664
+ provider: this,
665
+ id: user.id,
666
+ name: user.name ?? undefined,
667
+ email: user.email ?? undefined,
668
+ avatarUrl: user.avatarUrl ?? undefined,
669
+ username: user.username ?? undefined,
670
+ }
671
+ : undefined;
672
+ }
673
+ }
674
+
675
+ export function convertTokentoPAT(accessToken: string): string {
676
+ return base64(`PAT:${accessToken}`);
677
+ }