@gitkraken/core-gitlens 0.5.116 → 0.6.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 (44) hide show
  1. package/CHANGELOG.md +18 -1
  2. package/dist/git/models/issue.d.ts +14 -1
  3. package/dist/git/models/issue.d.ts.map +1 -1
  4. package/dist/git/models/issue.js +5 -1
  5. package/dist/git/models/issue.js.map +1 -1
  6. package/dist/git/models/pullRequest.d.ts +8 -2
  7. package/dist/git/models/pullRequest.d.ts.map +1 -1
  8. package/dist/git/remotes/azure-devops.d.ts +11 -1
  9. package/dist/git/remotes/azure-devops.d.ts.map +1 -1
  10. package/dist/git/remotes/azure-devops.js +47 -12
  11. package/dist/git/remotes/azure-devops.js.map +1 -1
  12. package/dist/git/utils/issue.utils.d.ts.map +1 -1
  13. package/dist/git/utils/issue.utils.js +9 -0
  14. package/dist/git/utils/issue.utils.js.map +1 -1
  15. package/dist/plus/integrations/providers/azure/azure.d.ts +13 -0
  16. package/dist/plus/integrations/providers/azure/azure.d.ts.map +1 -1
  17. package/dist/plus/integrations/providers/azure/azure.js +79 -16
  18. package/dist/plus/integrations/providers/azure/azure.js.map +1 -1
  19. package/dist/plus/integrations/providers/azure/models.d.ts +37 -10
  20. package/dist/plus/integrations/providers/azure/models.d.ts.map +1 -1
  21. package/dist/plus/integrations/providers/azure/models.js +118 -52
  22. package/dist/plus/integrations/providers/azure/models.js.map +1 -1
  23. package/dist/plus/integrations/providers/azureDevOps.d.ts +1 -0
  24. package/dist/plus/integrations/providers/azureDevOps.d.ts.map +1 -1
  25. package/dist/plus/integrations/providers/azureDevOps.js +19 -7
  26. package/dist/plus/integrations/providers/azureDevOps.js.map +1 -1
  27. package/dist/plus/integrations/providers/models.d.ts.map +1 -1
  28. package/dist/plus/integrations/providers/models.js +15 -4
  29. package/dist/plus/integrations/providers/models.js.map +1 -1
  30. package/dist/plus/integrations/reads/resolveRepository.d.ts.map +1 -1
  31. package/dist/plus/integrations/reads/resolveRepository.js +2 -0
  32. package/dist/plus/integrations/reads/resolveRepository.js.map +1 -1
  33. package/docs/integrations.md +33 -0
  34. package/docs/kepler-read-api-parity.md +15 -12
  35. package/package.json +1 -1
  36. package/src/git/models/issue.ts +15 -0
  37. package/src/git/models/pullRequest.ts +6 -2
  38. package/src/git/remotes/azure-devops.ts +68 -14
  39. package/src/git/utils/issue.utils.ts +10 -0
  40. package/src/plus/integrations/providers/azure/azure.ts +147 -16
  41. package/src/plus/integrations/providers/azure/models.ts +165 -63
  42. package/src/plus/integrations/providers/azureDevOps.ts +22 -13
  43. package/src/plus/integrations/providers/models.ts +22 -5
  44. package/src/plus/integrations/reads/resolveRepository.ts +3 -0
@@ -76,6 +76,17 @@ function getAzureRepositoryIdentity(repo: Pick<AzureRepositoryDescriptor, 'owner
76
76
  };
77
77
  }
78
78
 
79
+ function getAzureRepositoryApiBaseUrl(baseUrl: string, repo: Pick<AzureRepositoryDescriptor, 'virtualDirectory'>) {
80
+ if (repo.virtualDirectory == null) return baseUrl;
81
+
82
+ const segments = repo.virtualDirectory.split('/');
83
+ if (segments.some(segment => !segment || segment === '.' || segment === '..')) {
84
+ throw new Error(`Invalid Azure virtual directory '${repo.virtualDirectory}'.`);
85
+ }
86
+
87
+ return `${baseUrl.replace(/\/+$/, '')}/${segments.map(encodeURIComponent).join('/')}`;
88
+ }
89
+
79
90
  /**
80
91
  * Matches an org/project descriptor against a caller-supplied name, mirroring the facade's own
81
92
  * key/id/name comparison so `listIssuesPage({ org, project })` narrows on the same identifiers a consumer
@@ -502,7 +513,7 @@ export abstract class AzureDevOpsIntegrationBase<
502
513
  repo.owner,
503
514
  repo.name,
504
515
  rev,
505
- this.apiBaseUrl,
516
+ getAzureRepositoryApiBaseUrl(this.apiBaseUrl, repo),
506
517
  options,
507
518
  );
508
519
  }
@@ -528,7 +539,7 @@ export abstract class AzureDevOpsIntegrationBase<
528
539
  toTokenWithInfo(this.id, session),
529
540
  repo.owner,
530
541
  repo.name,
531
- { baseUrl: this.apiBaseUrl },
542
+ { baseUrl: getAzureRepositoryApiBaseUrl(this.apiBaseUrl, repo) },
532
543
  cancellation,
533
544
  );
534
545
  }
@@ -546,7 +557,7 @@ export abstract class AzureDevOpsIntegrationBase<
546
557
  repo.name,
547
558
  id,
548
559
  {
549
- baseUrl: this.apiBaseUrl,
560
+ baseUrl: getAzureRepositoryApiBaseUrl(this.apiBaseUrl, repo),
550
561
  type: type,
551
562
  },
552
563
  );
@@ -596,7 +607,7 @@ export abstract class AzureDevOpsIntegrationBase<
596
607
  repo.name,
597
608
  branch,
598
609
  {
599
- baseUrl: this.apiBaseUrl,
610
+ baseUrl: getAzureRepositoryApiBaseUrl(this.apiBaseUrl, repo),
600
611
  },
601
612
  );
602
613
  }
@@ -612,7 +623,7 @@ export abstract class AzureDevOpsIntegrationBase<
612
623
  repo.owner,
613
624
  repo.name,
614
625
  rev,
615
- this.apiBaseUrl,
626
+ getAzureRepositoryApiBaseUrl(this.apiBaseUrl, repo),
616
627
  );
617
628
  }
618
629
 
@@ -620,6 +631,7 @@ export abstract class AzureDevOpsIntegrationBase<
620
631
  owner: string;
621
632
  name: string;
622
633
  project?: string;
634
+ virtualDirectory?: string;
623
635
  connectionId?: string;
624
636
  }): Promise<ProviderRepository | undefined> {
625
637
  const identity = getAzureRepositoryIdentity(repo);
@@ -631,13 +643,10 @@ export abstract class AzureDevOpsIntegrationBase<
631
643
  if (session == null) return undefined;
632
644
 
633
645
  const { tokenWithInfo, options } = this.getApiOptions(session);
634
- return api.getRepo(
635
- tokenWithInfo,
636
- identity.resourceName,
637
- identity.repositoryName,
638
- identity.projectName,
639
- options,
640
- );
646
+ return api.getRepo(tokenWithInfo, identity.resourceName, identity.repositoryName, identity.projectName, {
647
+ ...options,
648
+ baseUrl: getAzureRepositoryApiBaseUrl(this.apiBaseUrl, repo),
649
+ });
641
650
  }
642
651
 
643
652
  protected override async getProviderRepositoryMetadata(
@@ -650,7 +659,7 @@ export abstract class AzureDevOpsIntegrationBase<
650
659
  toTokenWithInfo(this.id, session),
651
660
  repo.owner,
652
661
  repo.name,
653
- { baseUrl: this.apiBaseUrl },
662
+ { baseUrl: getAzureRepositoryApiBaseUrl(this.apiBaseUrl, repo) },
654
663
  cancellation,
655
664
  );
656
665
  }
@@ -47,7 +47,7 @@ import { EntityIdentifierUtils } from '@gitkraken/provider-apis/entity-identifie
47
47
  import { GitProviderUtils } from '@gitkraken/provider-apis/provider-utils';
48
48
  import { githubSearchResultLimit } from '../../git-github/api/config.js';
49
49
  import type { Account as UserAccount } from '../../../git/models/author.js';
50
- import type { IssueProject, IssueShape, IssueStateFilter } from '../../../git/models/issue.js';
50
+ import type { IssueProject, IssueProviderState, IssueShape, IssueStateFilter } from '../../../git/models/issue.js';
51
51
  import { Issue, RepositoryAccessLevel } from '../../../git/models/issue.js';
52
52
  import type {
53
53
  PullRequestRef,
@@ -1229,6 +1229,20 @@ function toIssueIdentifier(value: string | number): string {
1229
1229
  return String(value);
1230
1230
  }
1231
1231
 
1232
+ function toIssueProviderState(
1233
+ state: ProviderIssue['state'],
1234
+ reliableStateCategory = true,
1235
+ ): IssueProviderState | undefined {
1236
+ return state == null
1237
+ ? undefined
1238
+ : {
1239
+ id: state.id,
1240
+ name: state.name,
1241
+ color: state.color ?? undefined,
1242
+ category: reliableStateCategory ? state.category : undefined,
1243
+ };
1244
+ }
1245
+
1232
1246
  export function toIssueShape(
1233
1247
  issue: ProviderIssue,
1234
1248
  provider: ProviderReference,
@@ -1242,10 +1256,9 @@ export function toIssueShape(
1242
1256
 
1243
1257
  // Jira SDK results derive this category from a localized display name and default unknown names to DONE.
1244
1258
  // Only the direct point read opts in because it maps Jira's stable status-category key itself.
1245
- const closed =
1246
- issue.closedDate != null ||
1247
- (issue.state?.category === 'DONE' &&
1248
- (provider.id !== IssuesCloudHostIntegrationId.Jira || options?.reliableStateCategory === true));
1259
+ const reliableStateCategory =
1260
+ provider.id !== IssuesCloudHostIntegrationId.Jira || options?.reliableStateCategory === true;
1261
+ const closed = issue.closedDate != null || (issue.state?.category === 'DONE' && reliableStateCategory);
1249
1262
 
1250
1263
  return {
1251
1264
  type: 'issue',
@@ -1267,6 +1280,7 @@ export function toIssueShape(
1267
1280
  closedDate: issue.closedDate ?? undefined,
1268
1281
  closed: closed,
1269
1282
  state: closed ? 'closed' : 'opened',
1283
+ providerState: toIssueProviderState(issue.state, reliableStateCategory),
1270
1284
  author: {
1271
1285
  id: issue.author?.id ?? '',
1272
1286
  // An absent name stays absent, matching {@link fromProviderAccount}; see `IssueMember.name`.
@@ -1302,6 +1316,7 @@ export function toIssueShape(
1302
1316
  commentsCount: issue.commentCount ?? undefined,
1303
1317
  thumbsUpCount: issue.upvoteCount ?? undefined,
1304
1318
  body: issue.description ?? undefined,
1319
+ bodyFormat: provider.id === IssuesCloudHostIntegrationId.Jira ? 'jira-wiki' : undefined,
1305
1320
  issueType: issue.type ?? undefined,
1306
1321
  };
1307
1322
  }
@@ -1741,6 +1756,8 @@ export function fromProviderIssue(
1741
1756
  : undefined,
1742
1757
  identifier,
1743
1758
  issue.type ?? undefined,
1759
+ toIssueProviderState(issue.state, integration.id !== IssuesCloudHostIntegrationId.Jira),
1760
+ integration.id === IssuesCloudHostIntegrationId.Jira ? 'jira-wiki' : undefined,
1744
1761
  );
1745
1762
  }
1746
1763
 
@@ -96,6 +96,8 @@ export async function resolveRepository(
96
96
  const name = provider.repoName;
97
97
  if (owner == null || name == null) return result('invalid-remote-url');
98
98
 
99
+ const providerRepo = provider.repoDesc;
100
+
99
101
  // On a self-managed host, resolve only against a TRUSTED host: the pinned connection's configured
100
102
  // domain, the explicit `domain`, or — when neither was supplied — a configured host matching the
101
103
  // remote's. That last case keeps `remoteUrl` (repository-supplied) out of the trusted path: it selects
@@ -164,6 +166,7 @@ export async function resolveRepository(
164
166
 
165
167
  try {
166
168
  const repo = await integration.getRepoInfo({
169
+ ...providerRepo,
167
170
  owner: owner,
168
171
  name: name,
169
172
  project: project,