@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,691 @@
1
+ import type { UnidentifiedAuthor } from '../../../../git/models/author.js';
2
+ import type { Issue } from '../../../../git/models/issue.js';
3
+ import type { IssueOrPullRequest, IssueOrPullRequestType } from '../../../../git/models/issueOrPullRequest.js';
4
+ import type { PullRequest } from '../../../../git/models/pullRequest.js';
5
+ import type { Provider } from '../../../../git/models/remoteProvider.js';
6
+ import { base64 } from '../../../../utils/base64.js';
7
+ import { CancellationError } from '../../../../utils/cancellation.js';
8
+ import { trace } from '../../../../utils/decorators/log.js';
9
+ import type { Disposable } from '../../../../utils/disposable.js';
10
+ import { Logger } from '../../../../utils/logger.js';
11
+ import type { ScopedLogger } from '../../../../utils/logger.scoped.js';
12
+ import { getScopedLogger } from '../../../../utils/logger.scoped.js';
13
+ import { maybeStopWatch } from '../../../../utils/stopwatch.js';
14
+ import type { TokenInfo, TokenWithInfo } from '../../authentication/models.js';
15
+ import type { IntegrationServiceContext } from '../../context.js';
16
+ import {
17
+ AuthenticationError,
18
+ AuthenticationErrorReason,
19
+ ProviderFetchError,
20
+ RequestClientError,
21
+ RequestNotFoundError,
22
+ } from '../../errors.js';
23
+ import type {
24
+ AzureGitCommit,
25
+ AzureProjectDescriptor,
26
+ AzurePullRequest,
27
+ AzurePullRequestWithLinks,
28
+ AzureWorkItemState,
29
+ AzureWorkItemStateCategory,
30
+ WorkItem,
31
+ } from './models.js';
32
+ import {
33
+ azurePullRequestStatusToState,
34
+ azureWorkItemsStateCategoryToState,
35
+ fromAzurePullRequest,
36
+ fromAzureWorkItem,
37
+ getAzurePullRequestWebUrl,
38
+ isClosedAzurePullRequestStatus,
39
+ isClosedAzureWorkItemStateCategory,
40
+ } from './models.js';
41
+
42
+ class WorkItemStates {
43
+ private readonly _categories = new Map<string, AzureWorkItemStateCategory>();
44
+ private readonly _types = new Map<string, AzureWorkItemState[]>();
45
+
46
+ // TODO@sergeibbb: we might need some logic for invalidating
47
+ public getStateCategory(
48
+ project: string,
49
+ workItemType: string,
50
+ stateName: string,
51
+ ): AzureWorkItemStateCategory | undefined {
52
+ return this._categories.get(this.getStateKey(project, workItemType, stateName));
53
+ }
54
+
55
+ public clear(): void {
56
+ this._categories.clear();
57
+ this._types.clear();
58
+ }
59
+
60
+ public saveTypeStates(project: string, workItemType: string, states: AzureWorkItemState[]): void {
61
+ this.clearTypeStates(project, workItemType);
62
+ this._types.set(this.getTypeKey(project, workItemType), states);
63
+ for (const state of states) {
64
+ this._categories.set(this.getStateKey(project, workItemType, state.name), state.category);
65
+ }
66
+ }
67
+
68
+ public hasTypeStates(project: string, workItemType: string): boolean {
69
+ return this._types.has(this.getTypeKey(project, workItemType));
70
+ }
71
+
72
+ private clearTypeStates(project: string, workItemType: string): void {
73
+ const states = this._types.get(this.getTypeKey(project, workItemType));
74
+ if (states == null) return;
75
+
76
+ for (const state of states) {
77
+ this._categories.delete(this.getStateKey(project, workItemType, state.name));
78
+ }
79
+ }
80
+
81
+ private getStateKey(project: string, workItemType: string, stateName: string): string {
82
+ // By stringifying the pair as JSON we make sure that all possible special characters are escaped
83
+ return JSON.stringify([project, workItemType, stateName]);
84
+ }
85
+
86
+ private getTypeKey(project: string, workItemType: string): string {
87
+ return JSON.stringify([project, workItemType]);
88
+ }
89
+ }
90
+
91
+ export class AzureDevOpsApi implements Disposable {
92
+ private readonly _disposable: Disposable;
93
+ private _workItemStates: WorkItemStates = new WorkItemStates();
94
+
95
+ constructor(private readonly ctx: IntegrationServiceContext) {
96
+ this._disposable = ctx.config.onDidChange(e => {
97
+ if (e.httpProxy) {
98
+ this.resetCaches();
99
+ }
100
+ });
101
+ }
102
+
103
+ dispose(): void {
104
+ this._disposable.dispose();
105
+ }
106
+
107
+ private resetCaches(): void {
108
+ this._workItemStates.clear();
109
+ }
110
+
111
+ @trace({
112
+ args: (provider, token, owner, repo, branch) => ({
113
+ provider: provider.name,
114
+ token: `<token:${token.microHash}>`,
115
+ owner: owner,
116
+ repo: repo,
117
+ branch: branch,
118
+ }),
119
+ })
120
+ public async getPullRequestForBranch(
121
+ provider: Provider,
122
+ token: TokenWithInfo,
123
+ owner: string,
124
+ repo: string,
125
+ branch: string,
126
+ options: {
127
+ baseUrl: string;
128
+ },
129
+ ): Promise<PullRequest | undefined> {
130
+ const scope = getScopedLogger();
131
+ const [projectName, _, repoName] = repo.split('/');
132
+
133
+ try {
134
+ const prResult = await this.request<{ value: AzurePullRequest[] }>(
135
+ provider,
136
+ token,
137
+ options?.baseUrl,
138
+ `${owner}/${projectName}/_apis/git/repositories/${repoName}/pullRequests?searchCriteria.status=all&searchCriteria.sourceRefName=refs/heads/${branch}`,
139
+ {
140
+ method: 'GET',
141
+ },
142
+ scope,
143
+ );
144
+
145
+ // Sort PRs: open PRs first, then by most recent activity (creation or closure date)
146
+ const sortedPRs = prResult?.value.sort((a, b) => {
147
+ // First, prioritize open PRs (active/notSet) over closed ones (abandoned/completed)
148
+ const aIsOpen = a.status === 'active' || a.status === 'notSet';
149
+ const bIsOpen = b.status === 'active' || b.status === 'notSet';
150
+
151
+ if (aIsOpen !== bIsOpen) {
152
+ return aIsOpen ? -1 : 1; // Open PRs come first
153
+ }
154
+
155
+ // Among PRs with the same status, sort by most recent activity
156
+ // Use closedDate if available, otherwise use creationDate
157
+ const aDate = new Date(a.closedDate || a.creationDate);
158
+ const bDate = new Date(b.closedDate || b.creationDate);
159
+
160
+ return bDate.getTime() - aDate.getTime(); // Most recent first
161
+ });
162
+
163
+ const pr = sortedPRs?.[0];
164
+ if (pr == null) return undefined;
165
+
166
+ return fromAzurePullRequest(pr, provider, owner);
167
+ } catch (ex) {
168
+ scope?.error(ex);
169
+ return undefined;
170
+ }
171
+ }
172
+
173
+ @trace({
174
+ args: (provider, token, owner, repo, rev, baseUrl) => ({
175
+ provider: provider.name,
176
+ token: `<token:${token.microHash}>`,
177
+ owner: owner,
178
+ repo: repo,
179
+ rev: rev,
180
+ baseUrl: baseUrl,
181
+ }),
182
+ })
183
+ async getPullRequestForCommit(
184
+ provider: Provider,
185
+ token: TokenWithInfo,
186
+ owner: string,
187
+ repo: string,
188
+ rev: string,
189
+ baseUrl: string,
190
+ _options?: {
191
+ avatarSize?: number;
192
+ },
193
+ cancellation?: AbortSignal,
194
+ ): Promise<PullRequest | undefined> {
195
+ const scope = getScopedLogger();
196
+ const [projectName, _, repoName] = repo.split('/');
197
+ try {
198
+ const prResult = await this.request<{ results: Record<string, AzurePullRequest[]>[] }>(
199
+ provider,
200
+ token,
201
+ baseUrl,
202
+ `${owner}/${projectName}/_apis/git/repositories/${repoName}/pullrequestquery?api-version=4.1`,
203
+ {
204
+ method: 'POST',
205
+ body: JSON.stringify({
206
+ queries: [
207
+ {
208
+ items: [rev],
209
+ type: 'commit',
210
+ },
211
+ ],
212
+ }),
213
+ },
214
+ scope,
215
+ cancellation,
216
+ );
217
+
218
+ const pr = prResult?.results[0]?.[rev]?.[0];
219
+ if (pr == null) return undefined;
220
+
221
+ const pullRequest = await this.request<AzurePullRequestWithLinks>(
222
+ provider,
223
+ token,
224
+ undefined,
225
+ pr.url,
226
+ { method: 'GET' },
227
+ scope,
228
+ cancellation,
229
+ );
230
+ if (pullRequest == null) return undefined;
231
+
232
+ return fromAzurePullRequest(pullRequest, provider, owner);
233
+ } catch (ex) {
234
+ scope?.error(ex);
235
+ return undefined;
236
+ }
237
+ }
238
+
239
+ @trace({
240
+ args: (provider, token, owner, repo, id) => ({
241
+ provider: provider.name,
242
+ token: `<token:${token.microHash}>`,
243
+ owner: owner,
244
+ repo: repo,
245
+ id: id,
246
+ }),
247
+ })
248
+ public async getIssueOrPullRequest(
249
+ provider: Provider,
250
+ token: TokenWithInfo,
251
+ owner: string,
252
+ repo: string,
253
+ id: string,
254
+ options: {
255
+ baseUrl: string;
256
+ type?: IssueOrPullRequestType;
257
+ },
258
+ ): Promise<IssueOrPullRequest | undefined> {
259
+ const scope = getScopedLogger();
260
+ const [projectName, _, repoName] = repo.split('/');
261
+
262
+ if (options?.type === undefined || options?.type === 'issue') {
263
+ try {
264
+ // Try to get the Work item (wit) first with specific fields
265
+ const issueResult = await this.request<WorkItem>(
266
+ provider,
267
+ token,
268
+ options?.baseUrl,
269
+ `${owner}/${projectName}/_apis/wit/workItems/${id}`,
270
+ {
271
+ method: 'GET',
272
+ },
273
+ scope,
274
+ );
275
+
276
+ if (issueResult != null) {
277
+ const issueType = issueResult.fields['System.WorkItemType'];
278
+ const state = issueResult.fields['System.State'];
279
+ const stateCategory = await this.getWorkItemStateCategory(
280
+ issueType,
281
+ state,
282
+ provider,
283
+ token,
284
+ owner,
285
+ projectName,
286
+ options,
287
+ );
288
+
289
+ return {
290
+ id: issueResult.id.toString(),
291
+ type: 'issue',
292
+ nodeId: issueResult.id.toString(),
293
+ provider: provider,
294
+ createdDate: new Date(issueResult.fields['System.CreatedDate']),
295
+ updatedDate: new Date(issueResult.fields['System.ChangedDate']),
296
+ state: azureWorkItemsStateCategoryToState(stateCategory),
297
+ closed: isClosedAzureWorkItemStateCategory(stateCategory),
298
+ title: issueResult.fields['System.Title'],
299
+ url: issueResult._links.html.href,
300
+ };
301
+ }
302
+ } catch (ex) {
303
+ if (ex.original?.status !== 404) {
304
+ scope?.error(ex);
305
+ return undefined;
306
+ }
307
+ }
308
+ }
309
+
310
+ if (options?.type === undefined || options?.type === 'pullrequest') {
311
+ try {
312
+ const prResult = await this.request<AzurePullRequestWithLinks>(
313
+ provider,
314
+ token,
315
+ options?.baseUrl,
316
+ `${owner}/${projectName}/_apis/git/repositories/${repoName}/pullRequests/${id}`,
317
+ {
318
+ method: 'GET',
319
+ },
320
+ scope,
321
+ );
322
+
323
+ if (prResult != null) {
324
+ return {
325
+ id: prResult.pullRequestId.toString(),
326
+ type: 'pullrequest',
327
+ nodeId: prResult.pullRequestId.toString(), // prResult.artifactId maybe?
328
+ provider: provider,
329
+ createdDate: new Date(prResult.creationDate),
330
+ updatedDate: new Date(prResult.creationDate),
331
+ state: azurePullRequestStatusToState(prResult.status),
332
+ closed: isClosedAzurePullRequestStatus(prResult.status),
333
+ title: prResult.title,
334
+ url: getAzurePullRequestWebUrl(prResult),
335
+ };
336
+ }
337
+
338
+ return undefined;
339
+ } catch (ex) {
340
+ if (ex.original?.status !== 404) {
341
+ scope?.error(ex);
342
+ return undefined;
343
+ }
344
+ }
345
+ }
346
+ return undefined;
347
+ }
348
+
349
+ @trace({
350
+ args: (provider, token, project, id) => ({
351
+ provider: provider.name,
352
+ token: `<token:${token.microHash}>`,
353
+ project: project,
354
+ id: id,
355
+ }),
356
+ })
357
+ public async getIssue(
358
+ provider: Provider,
359
+ token: TokenWithInfo,
360
+ project: AzureProjectDescriptor,
361
+ id: string,
362
+ options: {
363
+ baseUrl: string;
364
+ },
365
+ ): Promise<Issue | undefined> {
366
+ const scope = getScopedLogger();
367
+
368
+ try {
369
+ // Try to get the Work item (wit) first with specific fields
370
+ const issueResult = await this.request<WorkItem>(
371
+ provider,
372
+ token,
373
+ options?.baseUrl,
374
+ `${project.resourceName}/${project.name}/_apis/wit/workItems/${id}`,
375
+ {
376
+ method: 'GET',
377
+ },
378
+ scope,
379
+ );
380
+
381
+ if (issueResult != null) {
382
+ const issueType = issueResult.fields['System.WorkItemType'];
383
+ const state = issueResult.fields['System.State'];
384
+ const stateCategory = await this.getWorkItemStateCategory(
385
+ issueType,
386
+ state,
387
+ provider,
388
+ token,
389
+ project.resourceName,
390
+ project.name,
391
+ options,
392
+ );
393
+ return fromAzureWorkItem(issueResult, provider, project, stateCategory);
394
+ }
395
+ } catch (ex) {
396
+ if (ex.original?.status !== 404) {
397
+ scope?.error(ex);
398
+ return undefined;
399
+ }
400
+ }
401
+
402
+ return undefined;
403
+ }
404
+
405
+ @trace({
406
+ args: (provider, token, owner, repo, rev, baseUrl) => ({
407
+ provider: provider.name,
408
+ token: `<token:${token.microHash}>`,
409
+ owner: owner,
410
+ repo: repo,
411
+ rev: rev,
412
+ baseUrl: baseUrl,
413
+ }),
414
+ })
415
+ async getAccountForCommit(
416
+ provider: Provider,
417
+ token: TokenWithInfo,
418
+ owner: string,
419
+ repo: string,
420
+ rev: string,
421
+ baseUrl: string,
422
+ _options?: {
423
+ avatarSize?: number;
424
+ },
425
+ ): Promise<UnidentifiedAuthor | undefined> {
426
+ const scope = getScopedLogger();
427
+ const [projectName, _, repoName] = repo.split('/');
428
+
429
+ try {
430
+ // Try to get the Work item (wit) first with specific fields
431
+ const commit = await this.request<AzureGitCommit>(
432
+ provider,
433
+ token,
434
+ baseUrl,
435
+ `${owner}/${projectName}/_apis/git/repositories/${repoName}/commits/${rev}`,
436
+ {
437
+ method: 'GET',
438
+ },
439
+ scope,
440
+ );
441
+ const author = commit?.author;
442
+ if (!author) {
443
+ return undefined;
444
+ }
445
+ // Azure API never gives us an id/username we can use, therefore we always return UnidentifiedAuthor
446
+ return {
447
+ provider: provider,
448
+ id: undefined,
449
+ username: undefined,
450
+ name: author?.name,
451
+ email: author?.email,
452
+ avatarUrl: undefined,
453
+ } satisfies UnidentifiedAuthor;
454
+ } catch (ex) {
455
+ if (ex.original?.status !== 404) {
456
+ scope?.error(ex);
457
+ return undefined;
458
+ }
459
+ }
460
+
461
+ return undefined;
462
+ }
463
+
464
+ @trace({
465
+ args: (provider, token, baseUrl) => ({
466
+ provider: provider.name,
467
+ token: `<token:${token.microHash}>`,
468
+ baseUrl: baseUrl,
469
+ }),
470
+ })
471
+ async getCurrentUserOnServer(
472
+ provider: Provider,
473
+ token: TokenWithInfo,
474
+ baseUrl: string,
475
+ ): Promise<{ id: string; name?: string; email?: string; username?: string; avatarUrl?: string } | undefined> {
476
+ const scope = getScopedLogger();
477
+
478
+ try {
479
+ const connectionData = await this.request<{
480
+ authenticatedUser?: {
481
+ id: string;
482
+ descriptor: string;
483
+ isActive: boolean;
484
+ metTypeId: number;
485
+ providerDisplayName?: string;
486
+ emailAddress?: string;
487
+ resourceVersion: 2;
488
+ subjectDescriptor: string;
489
+ properties?: {
490
+ Account?: {
491
+ $type: string;
492
+ $value: string;
493
+ };
494
+ };
495
+ };
496
+ }>(
497
+ provider,
498
+ token,
499
+ baseUrl,
500
+ '_apis/connectionData',
501
+ {
502
+ method: 'GET',
503
+ },
504
+ scope,
505
+ );
506
+
507
+ const user = connectionData?.authenticatedUser;
508
+ const username = user?.properties?.Account?.$value;
509
+ if (!username) {
510
+ return undefined;
511
+ }
512
+
513
+ return {
514
+ id: user.id,
515
+ name: user.providerDisplayName,
516
+ email: user.emailAddress,
517
+ username: username,
518
+ };
519
+ } catch (ex) {
520
+ scope?.error(ex, `Failed to get current user from ${baseUrl}`);
521
+ return undefined;
522
+ }
523
+ }
524
+
525
+ async getWorkItemStateCategory(
526
+ issueType: string,
527
+ state: string,
528
+ provider: Provider,
529
+ token: TokenWithInfo,
530
+ owner: string,
531
+ projectName: string,
532
+ options: {
533
+ baseUrl: string;
534
+ },
535
+ ): Promise<AzureWorkItemStateCategory | undefined> {
536
+ const project = `${owner}/${projectName}`;
537
+ const category = this._workItemStates.getStateCategory(project, issueType, state);
538
+ if (category != null) return category;
539
+
540
+ const states = await this.retrieveWorkItemTypeStates(issueType, provider, token, owner, projectName, options);
541
+ this._workItemStates.saveTypeStates(project, issueType, states);
542
+
543
+ return this._workItemStates.getStateCategory(project, issueType, state);
544
+ }
545
+
546
+ private async retrieveWorkItemTypeStates(
547
+ workItemType: string,
548
+ provider: Provider,
549
+ token: TokenWithInfo,
550
+ owner: string,
551
+ projectName: string,
552
+ options: {
553
+ baseUrl: string;
554
+ },
555
+ ): Promise<AzureWorkItemState[]> {
556
+ const scope = getScopedLogger();
557
+
558
+ try {
559
+ const issueResult = await this.request<{ value: AzureWorkItemState[]; count: number }>(
560
+ provider,
561
+ token,
562
+ options?.baseUrl,
563
+ `${owner}/${projectName}/_apis/wit/workItemTypes/${workItemType}/states`,
564
+ {
565
+ method: 'GET',
566
+ },
567
+ scope,
568
+ );
569
+
570
+ return issueResult?.value ?? [];
571
+ } catch (ex) {
572
+ scope?.error(ex);
573
+ return [];
574
+ }
575
+ }
576
+
577
+ private async request<T>(
578
+ provider: Provider,
579
+ token: TokenWithInfo,
580
+ baseUrl: string | undefined,
581
+ route: string,
582
+ options: { method: RequestInit['method'] } & Record<string, unknown>,
583
+ scope: ScopedLogger | undefined,
584
+ cancellation?: AbortSignal | undefined,
585
+ ): Promise<T | undefined> {
586
+ const { accessToken, ...tokenInfo } = token;
587
+ const url = baseUrl ? `${baseUrl}/${route}` : route;
588
+
589
+ let rsp: Response;
590
+ try {
591
+ const sw = maybeStopWatch(`[AZURE] ${options?.method ?? 'GET'} ${url}`, { log: { onlyExit: true } });
592
+
593
+ try {
594
+ if (cancellation?.aborted) throw new CancellationError();
595
+
596
+ rsp = await this.ctx.http.wrapForForcedInsecureSSL(provider.getIgnoreSSLErrors(), () =>
597
+ this.ctx.http.fetch(url, {
598
+ headers: {
599
+ Authorization: `Basic ${base64(`PAT:${accessToken}`)}`,
600
+ 'Content-Type': 'application/json',
601
+ },
602
+ signal: cancellation,
603
+ ...options,
604
+ }),
605
+ );
606
+
607
+ if (rsp.ok) {
608
+ return (await rsp.json()) as T;
609
+ }
610
+
611
+ throw new ProviderFetchError('AzureDevOps', rsp);
612
+ } finally {
613
+ sw?.stop();
614
+ }
615
+ } catch (ex) {
616
+ if (ex instanceof ProviderFetchError || ex.name === 'AbortError') {
617
+ this.handleRequestError(provider, tokenInfo, ex, scope);
618
+ } else if (Logger.isDebugging) {
619
+ this.ctx.hooks?.ui?.onError?.(`AzureDevOps request failed: ${ex.message}`);
620
+ }
621
+
622
+ throw ex;
623
+ }
624
+ }
625
+
626
+ private handleRequestError(
627
+ provider: Provider | undefined,
628
+ tokenInfo: TokenInfo,
629
+ ex: ProviderFetchError | (Error & { name: 'AbortError' }),
630
+ scope: ScopedLogger | undefined,
631
+ ): void {
632
+ if (ex.name === 'AbortError' || !(ex instanceof ProviderFetchError)) throw new CancellationError(ex);
633
+
634
+ switch (ex.status) {
635
+ case 404: // Not found
636
+ case 410: // Gone
637
+ case 422: // Unprocessable Entity
638
+ throw new RequestNotFoundError(ex);
639
+ case 401: // Unauthorized
640
+ throw new AuthenticationError(tokenInfo, AuthenticationErrorReason.Unauthorized, ex);
641
+ case 403: // Forbidden
642
+ // TODO: Learn the Azure API docs and put it in order:
643
+ // if (ex.message.includes('rate limit')) {
644
+ // let resetAt: number | undefined;
645
+
646
+ // const reset = ex.response?.headers?.get('x-ratelimit-reset');
647
+ // if (reset != null) {
648
+ // resetAt = parseInt(reset, 10);
649
+ // if (Number.isNaN(resetAt)) {
650
+ // resetAt = undefined;
651
+ // }
652
+ // }
653
+
654
+ // throw new RequestRateLimitError(ex, token, resetAt);
655
+ // }
656
+ throw new AuthenticationError(tokenInfo, AuthenticationErrorReason.Forbidden, ex);
657
+ case 500: // Internal Server Error
658
+ scope?.error(ex);
659
+ if (ex.response != null) {
660
+ provider?.trackRequestException();
661
+ this.ctx.hooks?.ui?.onRequestFailed?.(
662
+ `${provider?.name ?? 'AzureDevOps'} failed to respond and might be experiencing issues.${
663
+ provider == null || provider.id === 'azure'
664
+ ? ' Please visit the [AzureDevOps status page](https://status.dev.azure.com) for more information.'
665
+ : ''
666
+ }`,
667
+ );
668
+ }
669
+ return;
670
+ case 502: // Bad Gateway
671
+ scope?.error(ex);
672
+ // TODO: Learn the Azure API docs and put it in order:
673
+ // if (ex.message.includes('timeout')) {
674
+ // provider?.trackRequestException();
675
+ // void showIntegrationRequestTimedOutWarningMessage(provider?.name ?? 'Azure');
676
+ // return;
677
+ // }
678
+ break;
679
+ default:
680
+ if (ex.status >= 400 && ex.status < 500) throw new RequestClientError(ex);
681
+ break;
682
+ }
683
+
684
+ scope?.error(ex);
685
+ if (Logger.isDebugging) {
686
+ this.ctx.hooks?.ui?.onError?.(
687
+ `AzureDevOps request failed: ${(ex.response as any)?.errors?.[0]?.message ?? ex.message}`,
688
+ );
689
+ }
690
+ }
691
+ }