@gitkraken/core-gitlens 0.5.108 → 0.5.109
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -1
- package/dist/git/models/issue.d.ts +70 -0
- package/dist/git/models/issue.d.ts.map +1 -1
- package/dist/git/models/issue.js +17 -0
- package/dist/git/models/issue.js.map +1 -1
- package/dist/git/utils/issue.utils.d.ts +41 -1
- package/dist/git/utils/issue.utils.d.ts.map +1 -1
- package/dist/git/utils/issue.utils.js +80 -0
- package/dist/git/utils/issue.utils.js.map +1 -1
- package/dist/plus/git-github/api/github.d.ts +33 -6
- package/dist/plus/git-github/api/github.d.ts.map +1 -1
- package/dist/plus/git-github/api/github.js +137 -15
- package/dist/plus/git-github/api/github.js.map +1 -1
- package/dist/plus/git-github/api/issueSearchQuery.d.ts +49 -5
- package/dist/plus/git-github/api/issueSearchQuery.d.ts.map +1 -1
- package/dist/plus/git-github/api/issueSearchQuery.js +64 -6
- package/dist/plus/git-github/api/issueSearchQuery.js.map +1 -1
- package/dist/plus/integrations/collectionMetadata.d.ts +18 -0
- package/dist/plus/integrations/collectionMetadata.d.ts.map +1 -1
- package/dist/plus/integrations/collectionMetadata.js +24 -0
- package/dist/plus/integrations/collectionMetadata.js.map +1 -1
- package/dist/plus/integrations/integrationService.d.ts +15 -9
- package/dist/plus/integrations/integrationService.d.ts.map +1 -1
- package/dist/plus/integrations/integrationService.js.map +1 -1
- package/dist/plus/integrations/manager.d.ts +40 -26
- package/dist/plus/integrations/manager.d.ts.map +1 -1
- package/dist/plus/integrations/models/gitHostIntegration.d.ts +6 -31
- package/dist/plus/integrations/models/gitHostIntegration.d.ts.map +1 -1
- package/dist/plus/integrations/models/gitHostIntegration.js +11 -1
- package/dist/plus/integrations/models/gitHostIntegration.js.map +1 -1
- package/dist/plus/integrations/models/issueReads.d.ts +63 -1
- package/dist/plus/integrations/models/issueReads.d.ts.map +1 -1
- package/dist/plus/integrations/models/issuesIntegration.d.ts +7 -21
- package/dist/plus/integrations/models/issuesIntegration.d.ts.map +1 -1
- package/dist/plus/integrations/models/issuesIntegration.js.map +1 -1
- package/dist/plus/integrations/providerFilters.d.ts +1 -1
- package/dist/plus/integrations/providerFilters.d.ts.map +1 -1
- package/dist/plus/integrations/providers/azureDevOps.d.ts.map +1 -1
- package/dist/plus/integrations/providers/azureDevOps.js +1 -0
- package/dist/plus/integrations/providers/azureDevOps.js.map +1 -1
- package/dist/plus/integrations/providers/github.d.ts.map +1 -1
- package/dist/plus/integrations/providers/github.js +1 -0
- package/dist/plus/integrations/providers/github.js.map +1 -1
- package/dist/plus/integrations/providers/gitlab.d.ts.map +1 -1
- package/dist/plus/integrations/providers/gitlab.js +1 -0
- package/dist/plus/integrations/providers/gitlab.js.map +1 -1
- package/dist/plus/integrations/providers/issueSorts.d.ts +36 -0
- package/dist/plus/integrations/providers/issueSorts.d.ts.map +1 -0
- package/dist/plus/integrations/providers/issueSorts.js +76 -0
- package/dist/plus/integrations/providers/issueSorts.js.map +1 -0
- package/dist/plus/integrations/providers/jira.d.ts +3 -9
- package/dist/plus/integrations/providers/jira.d.ts.map +1 -1
- package/dist/plus/integrations/providers/jira.js +5 -1
- package/dist/plus/integrations/providers/jira.js.map +1 -1
- package/dist/plus/integrations/providers/linear.d.ts +24 -9
- package/dist/plus/integrations/providers/linear.d.ts.map +1 -1
- package/dist/plus/integrations/providers/linear.js +63 -5
- package/dist/plus/integrations/providers/linear.js.map +1 -1
- package/dist/plus/integrations/providers/models.d.ts +63 -7
- package/dist/plus/integrations/providers/models.d.ts.map +1 -1
- package/dist/plus/integrations/providers/models.js +55 -0
- package/dist/plus/integrations/providers/models.js.map +1 -1
- package/dist/plus/integrations/providers/providersApi.d.ts +18 -3
- package/dist/plus/integrations/providers/providersApi.d.ts.map +1 -1
- package/dist/plus/integrations/providers/providersApi.js +24 -7
- package/dist/plus/integrations/providers/providersApi.js.map +1 -1
- package/dist/plus/integrations/providers/trello.d.ts +3 -9
- package/dist/plus/integrations/providers/trello.d.ts.map +1 -1
- package/dist/plus/integrations/providers/trello.js +1 -0
- package/dist/plus/integrations/providers/trello.js.map +1 -1
- package/dist/plus/integrations/providers/utils/providerPaging.d.ts.map +1 -1
- package/dist/plus/integrations/providers/utils/providerPaging.js +5 -1
- package/dist/plus/integrations/providers/utils/providerPaging.js.map +1 -1
- package/dist/plus/integrations/reads/broaden.d.ts +6 -0
- package/dist/plus/integrations/reads/broaden.d.ts.map +1 -1
- package/dist/plus/integrations/reads/broaden.js.map +1 -1
- package/dist/plus/integrations/reads/counts.d.ts +8 -1
- package/dist/plus/integrations/reads/counts.d.ts.map +1 -1
- package/dist/plus/integrations/reads/counts.js.map +1 -1
- package/dist/plus/integrations/reads/filters.d.ts +59 -9
- package/dist/plus/integrations/reads/filters.d.ts.map +1 -1
- package/dist/plus/integrations/reads/filters.js +17 -0
- package/dist/plus/integrations/reads/filters.js.map +1 -1
- package/dist/plus/integrations/reads/issueTracker.d.ts +18 -1
- package/dist/plus/integrations/reads/issueTracker.d.ts.map +1 -1
- package/dist/plus/integrations/reads/issueTracker.js +40 -3
- package/dist/plus/integrations/reads/issueTracker.js.map +1 -1
- package/dist/plus/integrations/reads/issues.d.ts +27 -3
- package/dist/plus/integrations/reads/issues.d.ts.map +1 -1
- package/dist/plus/integrations/reads/issues.js +223 -123
- package/dist/plus/integrations/reads/issues.js.map +1 -1
- package/dist/plus/integrations/reads/ordering.d.ts +101 -0
- package/dist/plus/integrations/reads/ordering.d.ts.map +1 -0
- package/dist/plus/integrations/reads/ordering.js +48 -0
- package/dist/plus/integrations/reads/ordering.js.map +1 -0
- package/dist/plus/integrations/reads/searchIssues.d.ts +7 -2
- package/dist/plus/integrations/reads/searchIssues.d.ts.map +1 -1
- package/dist/plus/integrations/reads/searchIssues.js +9 -3
- package/dist/plus/integrations/reads/searchIssues.js.map +1 -1
- package/dist/plus/integrations/reads/warnings.d.ts +34 -2
- package/dist/plus/integrations/reads/warnings.d.ts.map +1 -1
- package/dist/plus/integrations/reads/warnings.js +47 -2
- package/dist/plus/integrations/reads/warnings.js.map +1 -1
- package/dist/plus/integrations/results.d.ts +10 -0
- package/dist/plus/integrations/results.d.ts.map +1 -1
- package/dist/plus/integrations/results.js.map +1 -1
- package/package.json +2 -2
- package/src/git/models/issue.ts +73 -0
- package/src/git/utils/issue.utils.ts +91 -1
- package/src/plus/git-github/api/github.ts +180 -20
- package/src/plus/git-github/api/issueSearchQuery.ts +67 -7
- package/src/plus/integrations/collectionMetadata.ts +24 -0
- package/src/plus/integrations/integrationService.ts +15 -10
- package/src/plus/integrations/manager.ts +40 -31
- package/src/plus/integrations/models/gitHostIntegration.ts +18 -31
- package/src/plus/integrations/models/issueReads.ts +65 -1
- package/src/plus/integrations/models/issuesIntegration.ts +7 -6
- package/src/plus/integrations/providerFilters.ts +2 -0
- package/src/plus/integrations/providers/azureDevOps.ts +1 -0
- package/src/plus/integrations/providers/github.ts +1 -0
- package/src/plus/integrations/providers/gitlab.ts +1 -0
- package/src/plus/integrations/providers/issueSorts.ts +89 -0
- package/src/plus/integrations/providers/jira.ts +9 -3
- package/src/plus/integrations/providers/linear.ts +77 -8
- package/src/plus/integrations/providers/models.ts +122 -5
- package/src/plus/integrations/providers/providersApi.ts +51 -13
- package/src/plus/integrations/providers/trello.ts +4 -3
- package/src/plus/integrations/providers/utils/providerPaging.ts +6 -1
- package/src/plus/integrations/reads/broaden.ts +6 -0
- package/src/plus/integrations/reads/counts.ts +8 -1
- package/src/plus/integrations/reads/filters.ts +70 -8
- package/src/plus/integrations/reads/issueTracker.ts +78 -4
- package/src/plus/integrations/reads/issues.ts +386 -194
- package/src/plus/integrations/reads/ordering.ts +124 -0
- package/src/plus/integrations/reads/searchIssues.ts +15 -3
- package/src/plus/integrations/reads/warnings.ts +72 -1
- package/src/plus/integrations/results.ts +10 -0
|
@@ -75,7 +75,7 @@ import {
|
|
|
75
75
|
IssuesCloudHostIntegrationId,
|
|
76
76
|
} from '../constants.js';
|
|
77
77
|
import type { Integration, IntegrationType } from '../models/integration.js';
|
|
78
|
-
import type { IssueSearchCapabilities, PullRequestSearchCapabilities } from '../providerFilters.js';
|
|
78
|
+
import type { IssueSearchCapabilities, IssueSorting, PullRequestSearchCapabilities } from '../providerFilters.js';
|
|
79
79
|
import { IssueFilter, PullRequestFilter } from '../providerFilters.js';
|
|
80
80
|
|
|
81
81
|
export { IssueFilter, PullRequestFilter } from '../providerFilters.js';
|
|
@@ -83,12 +83,25 @@ export type {
|
|
|
83
83
|
IssueSearchCapabilities,
|
|
84
84
|
IssueSearchCriteria,
|
|
85
85
|
IssueSearchRelationship,
|
|
86
|
+
IssueSortField,
|
|
87
|
+
IssueSorting,
|
|
86
88
|
PullRequestSearchCapabilities,
|
|
87
89
|
PullRequestSearchCriteria,
|
|
88
90
|
} from '../providerFilters.js';
|
|
89
91
|
import type { ProviderRepositoryShape } from '../results.js';
|
|
90
92
|
|
|
91
93
|
export type { ProviderOrganization, ProviderRepositoryShape } from '../results.js';
|
|
94
|
+
import {
|
|
95
|
+
azureAccountWideIssueSorts,
|
|
96
|
+
azureIssueSorts,
|
|
97
|
+
githubAccountWideIssueSorts,
|
|
98
|
+
githubIssueSorts,
|
|
99
|
+
gitlabAccountWideIssueSorts,
|
|
100
|
+
gitlabIssueSorts,
|
|
101
|
+
jiraIssueSorts,
|
|
102
|
+
linearIssueSorts,
|
|
103
|
+
trelloIssueSorts,
|
|
104
|
+
} from './issueSorts.js';
|
|
92
105
|
import { getEntityIdentifierInput } from './utils.js';
|
|
93
106
|
|
|
94
107
|
type GitBuildStatusState = GitBuildStatusStateType;
|
|
@@ -156,6 +169,28 @@ type EnrichableItem = any;
|
|
|
156
169
|
export type ProviderAccount = Account;
|
|
157
170
|
export type ProviderReposInput = (string | number)[] | GetRepoInput[];
|
|
158
171
|
export type ProviderRepoInput = GetRepoInput;
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Which half of {@link ProviderReposInput} a caller supplied: repository IDS rather than descriptors.
|
|
175
|
+
*
|
|
176
|
+
* The union has no discriminant, so the answer is the element shape — and several layers need it for different
|
|
177
|
+
* reasons (`ProvidersApi` to pick `repoIds` vs `repos` in the SDK input, `GitHostIntegration` to refuse an
|
|
178
|
+
* id-based read a provider can't serve, `listIssuesPage` to know GitLab's id form takes the SDK's own merging
|
|
179
|
+
* aggregate). One predicate rather than one per layer, because each copy is free to disagree about the shape,
|
|
180
|
+
* and the symptom of disagreement is a read routed to the wrong provider query.
|
|
181
|
+
*
|
|
182
|
+
* Takes `unknown` rather than {@link ProviderReposInput} because `ProvidersApi.isRepoIdsInput` forwards here and
|
|
183
|
+
* is public with an unvalidated parameter, so the array check has to stay part of the rule rather than be assumed
|
|
184
|
+
* from the parameter type.
|
|
185
|
+
*/
|
|
186
|
+
export function isRepoIdsInput(input: unknown): input is (string | number)[] {
|
|
187
|
+
return (
|
|
188
|
+
input != null &&
|
|
189
|
+
Array.isArray(input) &&
|
|
190
|
+
input.every(repo => typeof repo === 'string' || typeof repo === 'number')
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
|
|
159
194
|
export type ProviderPullRequest = GitPullRequest;
|
|
160
195
|
export type ProviderRepository = GitRepository;
|
|
161
196
|
export type ProviderIssue = ProviderApiIssue;
|
|
@@ -331,6 +366,20 @@ export interface GetIssuesOptions {
|
|
|
331
366
|
page?: number;
|
|
332
367
|
// Items to request per page (numbered-page providers, plus GitHub's maxPageSize).
|
|
333
368
|
pageSize?: number;
|
|
369
|
+
/**
|
|
370
|
+
* How the provider should order the result, as `field:direction`.
|
|
371
|
+
*
|
|
372
|
+
* Passed through to the SDK verbatim — the translation to each provider's own vocabulary lives THERE, next to
|
|
373
|
+
* the capability map it validates against, so that the table this facade publishes and the table that does the
|
|
374
|
+
* translating can't drift apart across two repositories. A key the provider can't express raises the SDK's
|
|
375
|
+
* `UnsupportedSortError`, which is why the facade validates against `supportedIssueSorts` first: reaching that
|
|
376
|
+
* error means this table has outrun the SDK's.
|
|
377
|
+
*
|
|
378
|
+
* Always supplied by the facade's reads, never omitted. Omitting it would delegate the order to each provider's
|
|
379
|
+
* own default, which is the incoherence across providers the SDK deliberately preserves and this layer
|
|
380
|
+
* deliberately does not.
|
|
381
|
+
*/
|
|
382
|
+
sort?: IssueSorting;
|
|
334
383
|
}
|
|
335
384
|
|
|
336
385
|
export interface GetIssuesForRepoInput extends GetIssuesOptions {
|
|
@@ -492,6 +541,8 @@ export type GetIssuesForCurrentUserInput = PagingInput & {
|
|
|
492
541
|
assigneeUsername?: string;
|
|
493
542
|
authorUsername?: string;
|
|
494
543
|
pageSize?: number;
|
|
544
|
+
/** See {@link GetIssuesOptions.sort}. */
|
|
545
|
+
sort?: IssueSorting;
|
|
495
546
|
};
|
|
496
547
|
|
|
497
548
|
export type GetIssuesForCurrentUserFn = (
|
|
@@ -624,10 +675,10 @@ export type GetBitbucketServerPullRequestsForCurrentUserFn = (
|
|
|
624
675
|
data: GitPullRequest[];
|
|
625
676
|
}>;
|
|
626
677
|
export type GetIssuesForProjectFn = Jira['getIssuesForProject'];
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
678
|
+
// Derived from the client method rather than hand-declared, as its project-scoped sibling above already is: the
|
|
679
|
+
// hand-written shape named only `resourceId`, so every other field the SDK accepts (the cursor, the sort, the
|
|
680
|
+
// transitions switch) was invisible to the type system and had to be smuggled through `getPagedResult`'s `any`.
|
|
681
|
+
export type GetIssuesForResourceForCurrentUserFn = Jira['getIssuesForResourceForCurrentUser'];
|
|
631
682
|
|
|
632
683
|
// Trello reads (issues-capable provider). The Trello client is keyed by an `appKey` (the Trello app key from
|
|
633
684
|
// the cloud token exchange) alongside the OAuth token, so these mirror the client method shapes directly.
|
|
@@ -729,6 +780,36 @@ export interface ProviderMetadata {
|
|
|
729
780
|
* axes; it omits `Mention` because that REST read has no first-class mention filter.
|
|
730
781
|
*/
|
|
731
782
|
supportedAccountWideIssueFilters?: IssueFilter[];
|
|
783
|
+
/**
|
|
784
|
+
* Sort keys the REPO-scoped issue read can express server-side — and, for an issue tracker (Jira/Linear/Trello),
|
|
785
|
+
* its project-scoped read, which is the only issue surface a tracker has.
|
|
786
|
+
*
|
|
787
|
+
* Absent/empty means the read can't be ordered at all, so a request carrying `sort` is refused rather than
|
|
788
|
+
* served in whatever order the provider felt like. Present, it is a promise: every key here reaches the
|
|
789
|
+
* provider query.
|
|
790
|
+
*
|
|
791
|
+
* A key listed here is expressible on ONE provider query, which is what this read is when it is given ONE
|
|
792
|
+
* scope. Given several (GitLab across repositories, Azure across projects, a tracker across projects) it merges
|
|
793
|
+
* their results here and can only honor a key a normalized issue carries, so it additionally refuses
|
|
794
|
+
* `priority`/`dueDate`/`resolved` — see `getIssueComparator`. That depends on the caller's scope count rather
|
|
795
|
+
* than on the provider, which is why it is a runtime refusal and not a fourth table: encoding it here would
|
|
796
|
+
* under-report the single-scope read, which really does support those keys.
|
|
797
|
+
*/
|
|
798
|
+
supportedIssueSorts?: IssueSorting[];
|
|
799
|
+
/**
|
|
800
|
+
* Sort keys the ACCOUNT-WIDE issue read can express server-side, which is NOT the same set as
|
|
801
|
+
* {@link ProviderMetadata.supportedIssueSorts} — for GitLab the two reads are different APIs (GraphQL vs REST)
|
|
802
|
+
* with genuinely different vocabularies, not one narrowed twice.
|
|
803
|
+
*
|
|
804
|
+
* Absent means the account-wide read can't be ordered (or doesn't exist). An issue tracker leaves this empty
|
|
805
|
+
* and reports under `supportedIssueSorts`, so reading a tracker's capability from here under-reports it.
|
|
806
|
+
*
|
|
807
|
+
* Unlike {@link ProviderMetadata.supportedIssueSorts} this needs no companion runtime refusal, because every
|
|
808
|
+
* provider's account-wide read is a union of several queries with no scope count for a caller to reduce: it
|
|
809
|
+
* ALWAYS merges. So the keys a merge can't order by are simply absent here — the table states what the read can
|
|
810
|
+
* honor, which is what makes intersecting against it sufficient.
|
|
811
|
+
*/
|
|
812
|
+
supportedAccountWideIssueSorts?: IssueSorting[];
|
|
732
813
|
/**
|
|
733
814
|
* What the provider's FILTERED issue search (`searchIssuesPage`, and the `countIssues` probe over the same
|
|
734
815
|
* criteria) can express server-side. A third, wider surface than either filter set above: it is not bound to
|
|
@@ -774,6 +855,8 @@ const githubIssueSearchCapabilities: IssueSearchCapabilities = {
|
|
|
774
855
|
withoutLinkedPullRequest: true,
|
|
775
856
|
// `is:open` / `is:closed`, or neither for all states.
|
|
776
857
|
states: true,
|
|
858
|
+
// `sort:created-desc`, `sort:updated`, `sort:comments-asc`, … — see `githubIssueSorts`.
|
|
859
|
+
sorts: githubIssueSorts,
|
|
777
860
|
};
|
|
778
861
|
|
|
779
862
|
/** GitHub and GHE use the same filtered pull-request search syntax and result ceiling. */
|
|
@@ -820,6 +903,10 @@ export const providersMetadata: ProvidersMetadata = {
|
|
|
820
903
|
// The account-wide read is three independent searches (`author:@me`, `assignee:@me`, `mentions:@me`) behind
|
|
821
904
|
// one composite cursor, so any subset of them is expressible.
|
|
822
905
|
supportedAccountWideIssueFilters: [IssueFilter.Author, IssueFilter.Assignee, IssueFilter.Mention],
|
|
906
|
+
// One `search` field serves all three issue reads (repo-scoped, account-wide, filtered search), so the same
|
|
907
|
+
// qualifiers are expressible on each — the account-wide one narrowed to what its three-alias merge can order.
|
|
908
|
+
supportedIssueSorts: githubIssueSorts,
|
|
909
|
+
supportedAccountWideIssueSorts: githubAccountWideIssueSorts,
|
|
823
910
|
supportedIssueSearch: githubIssueSearchCapabilities,
|
|
824
911
|
issueSearchResultLimit: githubSearchResultLimit,
|
|
825
912
|
scopes: ['repo', 'read:user', 'user:email'],
|
|
@@ -852,6 +939,10 @@ export const providersMetadata: ProvidersMetadata = {
|
|
|
852
939
|
// The account-wide read is three independent searches (`author:@me`, `assignee:@me`, `mentions:@me`) behind
|
|
853
940
|
// one composite cursor, so any subset of them is expressible.
|
|
854
941
|
supportedAccountWideIssueFilters: [IssueFilter.Author, IssueFilter.Assignee, IssueFilter.Mention],
|
|
942
|
+
// One `search` field serves all three issue reads (repo-scoped, account-wide, filtered search), so the same
|
|
943
|
+
// qualifiers are expressible on each — the account-wide one narrowed to what its three-alias merge can order.
|
|
944
|
+
supportedIssueSorts: githubIssueSorts,
|
|
945
|
+
supportedAccountWideIssueSorts: githubAccountWideIssueSorts,
|
|
855
946
|
supportedIssueSearch: githubIssueSearchCapabilities,
|
|
856
947
|
issueSearchResultLimit: githubSearchResultLimit,
|
|
857
948
|
scopes: ['repo', 'read:user', 'user:email'],
|
|
@@ -881,6 +972,10 @@ export const providersMetadata: ProvidersMetadata = {
|
|
|
881
972
|
// unioned, so either axis is expressible on its own. Mention is absent because GitLab's REST issue read has
|
|
882
973
|
// no first-class mention filter to narrow with.
|
|
883
974
|
supportedAccountWideIssueFilters: [IssueFilter.Assignee, IssueFilter.Author],
|
|
975
|
+
// Two different surfaces, not one narrowed twice: the repository-scoped read is GraphQL and the
|
|
976
|
+
// account-wide one is REST, and REST has neither `title` nor `closed_at`.
|
|
977
|
+
supportedIssueSorts: gitlabIssueSorts,
|
|
978
|
+
supportedAccountWideIssueSorts: gitlabAccountWideIssueSorts,
|
|
884
979
|
scopes: ['api', 'read_user', 'read_repository'],
|
|
885
980
|
},
|
|
886
981
|
[GitSelfManagedHostIntegrationId.CloudGitLabSelfHosted]: {
|
|
@@ -908,6 +1003,10 @@ export const providersMetadata: ProvidersMetadata = {
|
|
|
908
1003
|
// unioned, so either axis is expressible on its own. Mention is absent because GitLab's REST issue read has
|
|
909
1004
|
// no first-class mention filter to narrow with.
|
|
910
1005
|
supportedAccountWideIssueFilters: [IssueFilter.Assignee, IssueFilter.Author],
|
|
1006
|
+
// Two different surfaces, not one narrowed twice: the repository-scoped read is GraphQL and the
|
|
1007
|
+
// account-wide one is REST, and REST has neither `title` nor `closed_at`.
|
|
1008
|
+
supportedIssueSorts: gitlabIssueSorts,
|
|
1009
|
+
supportedAccountWideIssueSorts: gitlabAccountWideIssueSorts,
|
|
911
1010
|
scopes: ['api', 'read_user', 'read_repository'],
|
|
912
1011
|
},
|
|
913
1012
|
[GitCloudHostIntegrationId.Bitbucket]: {
|
|
@@ -956,6 +1055,11 @@ export const providersMetadata: ProvidersMetadata = {
|
|
|
956
1055
|
// The account-wide read drains one (project × assignee) and one (project × author) query per project, so
|
|
957
1056
|
// either axis is expressible on its own. There is no mention query to narrow to.
|
|
958
1057
|
supportedAccountWideIssueFilters: [IssueFilter.Author, IssueFilter.Assignee],
|
|
1058
|
+
// Both reads emit the same WIQL, but the account-wide one drains every (project x relationship) query and
|
|
1059
|
+
// merges the results, so it can only honor keys a normalized issue carries — `resolved` and `priority` are
|
|
1060
|
+
// dropped from that surface for the same reason they are dropped from GitLab's.
|
|
1061
|
+
supportedIssueSorts: azureIssueSorts,
|
|
1062
|
+
supportedAccountWideIssueSorts: azureAccountWideIssueSorts,
|
|
959
1063
|
scopes: ['vso.code', 'vso.identity', 'vso.project', 'vso.profile', 'vso.work'],
|
|
960
1064
|
},
|
|
961
1065
|
[GitSelfManagedHostIntegrationId.AzureDevOpsServer]: {
|
|
@@ -982,6 +1086,11 @@ export const providersMetadata: ProvidersMetadata = {
|
|
|
982
1086
|
// The account-wide read drains one (project × assignee) and one (project × author) query per project, so
|
|
983
1087
|
// either axis is expressible on its own. There is no mention query to narrow to.
|
|
984
1088
|
supportedAccountWideIssueFilters: [IssueFilter.Author, IssueFilter.Assignee],
|
|
1089
|
+
// Both reads emit the same WIQL, but the account-wide one drains every (project x relationship) query and
|
|
1090
|
+
// merges the results, so it can only honor keys a normalized issue carries — `resolved` and `priority` are
|
|
1091
|
+
// dropped from that surface for the same reason they are dropped from GitLab's.
|
|
1092
|
+
supportedIssueSorts: azureIssueSorts,
|
|
1093
|
+
supportedAccountWideIssueSorts: azureAccountWideIssueSorts,
|
|
985
1094
|
scopes: ['vso.code', 'vso.identity', 'vso.project', 'vso.profile', 'vso.work'],
|
|
986
1095
|
},
|
|
987
1096
|
[IssuesCloudHostIntegrationId.Jira]: {
|
|
@@ -1027,6 +1136,9 @@ export const providersMetadata: ProvidersMetadata = {
|
|
|
1027
1136
|
'read:project-version:jira',
|
|
1028
1137
|
],
|
|
1029
1138
|
supportedIssueFilters: [IssueFilter.Author, IssueFilter.Assignee, IssueFilter.Mention],
|
|
1139
|
+
// A tracker's issues live under resource -> project, so it has no account-wide surface to declare: its
|
|
1140
|
+
// capability is reported under `issues`, which is what `listIssueTrackerIssuesPage` validates against.
|
|
1141
|
+
supportedIssueSorts: jiraIssueSorts,
|
|
1030
1142
|
},
|
|
1031
1143
|
[IssuesCloudHostIntegrationId.Linear]: {
|
|
1032
1144
|
domain: 'linear.app',
|
|
@@ -1037,6 +1149,9 @@ export const providersMetadata: ProvidersMetadata = {
|
|
|
1037
1149
|
scopes: [],
|
|
1038
1150
|
// Linear scopes "my issues" client-side by the viewer's assignee id; author/mention aren't supported.
|
|
1039
1151
|
supportedIssueFilters: [IssueFilter.Assignee],
|
|
1152
|
+
// Both directions, and one table for both reads: they are the same root `issues` query taking the same
|
|
1153
|
+
// `sort` argument, so there is no account-wide narrowing to declare.
|
|
1154
|
+
supportedIssueSorts: linearIssueSorts,
|
|
1040
1155
|
},
|
|
1041
1156
|
[IssuesCloudHostIntegrationId.Trello]: {
|
|
1042
1157
|
domain: 'trello.com',
|
|
@@ -1047,6 +1162,8 @@ export const providersMetadata: ProvidersMetadata = {
|
|
|
1047
1162
|
scopes: [],
|
|
1048
1163
|
// Trello cards are filtered by the assignee (member) only; author/mention have no Trello equivalent.
|
|
1049
1164
|
supportedIssueFilters: [IssueFilter.Assignee],
|
|
1165
|
+
// `sort:edited` / `sort:-edited`. Trello's other search sorts (`created`, `due`) have no card-order effect.
|
|
1166
|
+
supportedIssueSorts: trelloIssueSorts,
|
|
1050
1167
|
},
|
|
1051
1168
|
};
|
|
1052
1169
|
|
|
@@ -39,6 +39,7 @@ import type {
|
|
|
39
39
|
GetPullRequestsOptions,
|
|
40
40
|
GetReposOptions,
|
|
41
41
|
IssueFilter,
|
|
42
|
+
IssueSorting,
|
|
42
43
|
PageInfo,
|
|
43
44
|
PagingInput,
|
|
44
45
|
PagingMode,
|
|
@@ -67,7 +68,7 @@ import type {
|
|
|
67
68
|
Providers,
|
|
68
69
|
PullRequestFilter,
|
|
69
70
|
} from './models.js';
|
|
70
|
-
import { providersMetadata } from './models.js';
|
|
71
|
+
import { isRepoIdsInput, providersMetadata } from './models.js';
|
|
71
72
|
import {
|
|
72
73
|
collectProviderPagedResult,
|
|
73
74
|
mergeCollectionMetadata,
|
|
@@ -132,6 +133,14 @@ function isGraphQLRepoNotFoundError(ex: unknown): boolean {
|
|
|
132
133
|
|
|
133
134
|
const trelloBaseUrl = 'https://api.trello.com';
|
|
134
135
|
|
|
136
|
+
/**
|
|
137
|
+
* Jira computes an issue's available transitions per issue, from the workflow and the reader's permissions, so a
|
|
138
|
+
* list read at a page size of 100 pays for 100 of those in both server work and response payload. Nothing in this
|
|
139
|
+
* package reads `statusTransitions` off a list — only the singular `getIssue` path exposes them, and it always
|
|
140
|
+
* expands them — so every list read opts out. Revisit the day a list row offers a status change straight off it.
|
|
141
|
+
*/
|
|
142
|
+
const jiraListIncludeTransitions = false;
|
|
143
|
+
|
|
135
144
|
type TrelloMemberResponse = {
|
|
136
145
|
id: string;
|
|
137
146
|
username?: string | null;
|
|
@@ -479,12 +488,9 @@ export class ProvidersApi {
|
|
|
479
488
|
);
|
|
480
489
|
}
|
|
481
490
|
|
|
482
|
-
isRepoIdsInput
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
Array.isArray(input) &&
|
|
486
|
-
input.every((id: any) => typeof id === 'string' || typeof id === 'number')
|
|
487
|
-
);
|
|
491
|
+
/** See {@link isRepoIdsInput}, which owns the rule; kept as a method because callers reach it through the api. */
|
|
492
|
+
isRepoIdsInput(input: unknown): input is (string | number)[] {
|
|
493
|
+
return isRepoIdsInput(input);
|
|
488
494
|
}
|
|
489
495
|
|
|
490
496
|
private async getProviderToken<T extends IntegrationIds>(
|
|
@@ -868,7 +874,10 @@ export class ProvidersApi {
|
|
|
868
874
|
async getLinearIssues(
|
|
869
875
|
tokenOptInfo: TokenWithInfo<IssuesCloudHostIntegrationId.Linear>,
|
|
870
876
|
input: { teams?: string[]; projects?: string[]; labels?: string[] },
|
|
871
|
-
options?: PagingInput
|
|
877
|
+
options?: PagingInput & {
|
|
878
|
+
/** See {@link GetIssuesOptions.sort}. Linear expresses `created`/`updated`, descending only. */
|
|
879
|
+
sort?: IssueSorting;
|
|
880
|
+
},
|
|
872
881
|
): Promise<PagedResult<ProviderIssue>> {
|
|
873
882
|
const { provider, tokenWithInfo } = await this.ensureProviderTokenAndFunction(
|
|
874
883
|
tokenOptInfo,
|
|
@@ -1565,6 +1574,8 @@ export class ProvidersApi {
|
|
|
1565
1574
|
*/
|
|
1566
1575
|
authorUsername?: string;
|
|
1567
1576
|
pageSize?: number;
|
|
1577
|
+
/** See {@link GetIssuesOptions.sort}. Forwarded to the provider fn; ordering is translated in the SDK. */
|
|
1578
|
+
sort?: IssueSorting;
|
|
1568
1579
|
isPAT?: boolean;
|
|
1569
1580
|
baseUrl?: string;
|
|
1570
1581
|
},
|
|
@@ -1580,6 +1591,7 @@ export class ProvidersApi {
|
|
|
1580
1591
|
authorUsername: options?.authorUsername,
|
|
1581
1592
|
page: options?.page,
|
|
1582
1593
|
pageSize: options?.pageSize,
|
|
1594
|
+
sort: options?.sort,
|
|
1583
1595
|
},
|
|
1584
1596
|
provider.getIssuesForCurrentUserFn,
|
|
1585
1597
|
tokenWithInfo,
|
|
@@ -1626,7 +1638,12 @@ export class ProvidersApi {
|
|
|
1626
1638
|
|
|
1627
1639
|
try {
|
|
1628
1640
|
const result = await provider.getIssuesForProjectFn?.(
|
|
1629
|
-
{
|
|
1641
|
+
{
|
|
1642
|
+
projectKey: project,
|
|
1643
|
+
resourceId: resourceId,
|
|
1644
|
+
...options,
|
|
1645
|
+
includeTransitions: jiraListIncludeTransitions,
|
|
1646
|
+
},
|
|
1630
1647
|
{ token: token },
|
|
1631
1648
|
);
|
|
1632
1649
|
|
|
@@ -1655,7 +1672,12 @@ export class ProvidersApi {
|
|
|
1655
1672
|
|
|
1656
1673
|
try {
|
|
1657
1674
|
const result = await provider.getIssuesForProjectFn?.(
|
|
1658
|
-
{
|
|
1675
|
+
{
|
|
1676
|
+
projectKey: project,
|
|
1677
|
+
resourceId: resourceId,
|
|
1678
|
+
...options,
|
|
1679
|
+
includeTransitions: jiraListIncludeTransitions,
|
|
1680
|
+
},
|
|
1659
1681
|
{ token: token },
|
|
1660
1682
|
);
|
|
1661
1683
|
if (result == null) return undefined;
|
|
@@ -1760,7 +1782,12 @@ export class ProvidersApi {
|
|
|
1760
1782
|
tokenOptInfo: TokenWithInfo,
|
|
1761
1783
|
appKey: string,
|
|
1762
1784
|
boardId: string,
|
|
1763
|
-
options?: {
|
|
1785
|
+
options?: {
|
|
1786
|
+
assigneeLogins?: string[];
|
|
1787
|
+
trelloBoardListsById?: Record<string, { name: string }>;
|
|
1788
|
+
/** See {@link GetIssuesOptions.sort}. Trello expresses only `updated`, in either direction. */
|
|
1789
|
+
sort?: IssueSorting;
|
|
1790
|
+
},
|
|
1764
1791
|
): Promise<ProviderApiCollectionResult<ProviderIssue>> {
|
|
1765
1792
|
const { provider, tokenWithInfo } = await this.ensureProviderTokenAndFunction(
|
|
1766
1793
|
tokenOptInfo,
|
|
@@ -1782,7 +1809,18 @@ export class ProvidersApi {
|
|
|
1782
1809
|
async getIssuesForResourceForCurrentUser(
|
|
1783
1810
|
tokenOptInfo: TokenWithInfo,
|
|
1784
1811
|
resourceId: string,
|
|
1785
|
-
options?: {
|
|
1812
|
+
options?: {
|
|
1813
|
+
cursor?: string;
|
|
1814
|
+
/**
|
|
1815
|
+
* See {@link GetIssuesOptions.sort}. Forwarded for the same reason as every sibling issue read, even
|
|
1816
|
+
* though nothing reaches this one with a sort today: `IssuesIntegration.searchProviderMyIssues` is the
|
|
1817
|
+
* only caller and takes no options. A wrapper that accepted the SDK's input and silently dropped one
|
|
1818
|
+
* field of it would give whoever adds that option no ordering and no error.
|
|
1819
|
+
*/
|
|
1820
|
+
sort?: IssueSorting;
|
|
1821
|
+
isPAT?: boolean;
|
|
1822
|
+
baseUrl?: string;
|
|
1823
|
+
},
|
|
1786
1824
|
): Promise<PagedResult<ProviderIssue>> {
|
|
1787
1825
|
const { provider, tokenWithInfo } = await this.ensureProviderTokenAndFunction(
|
|
1788
1826
|
tokenOptInfo,
|
|
@@ -1790,7 +1828,7 @@ export class ProvidersApi {
|
|
|
1790
1828
|
);
|
|
1791
1829
|
|
|
1792
1830
|
return this.getPagedResult<ProviderIssue>(
|
|
1793
|
-
{ resourceId: resourceId },
|
|
1831
|
+
{ resourceId: resourceId, sort: options?.sort, includeTransitions: jiraListIncludeTransitions },
|
|
1794
1832
|
provider.getIssuesForResourceForCurrentUserFn,
|
|
1795
1833
|
tokenWithInfo,
|
|
1796
1834
|
options?.cursor,
|
|
@@ -9,8 +9,8 @@ import type { ProviderAuthenticationSession } from '../authentication/models.js'
|
|
|
9
9
|
import { toTokenWithInfo } from '../authentication/models.js';
|
|
10
10
|
import { IssuesCloudHostIntegrationId } from '../constants.js';
|
|
11
11
|
import { IntegrationReadUnavailableError } from '../errors.js';
|
|
12
|
+
import type { IssuesForProjectOptions } from '../models/issueReads.js';
|
|
12
13
|
import { IssuesIntegration } from '../models/issuesIntegration.js';
|
|
13
|
-
import type { IssueFilter } from './models.js';
|
|
14
14
|
import { fromProviderIssue, providersMetadata, toIssueShape } from './models.js';
|
|
15
15
|
|
|
16
16
|
const metadata = providersMetadata[IssuesCloudHostIntegrationId.Trello];
|
|
@@ -95,7 +95,7 @@ export class TrelloIntegration extends IssuesIntegration<IssuesCloudHostIntegrat
|
|
|
95
95
|
protected override async getProviderIssuesForProject(
|
|
96
96
|
session: ProviderAuthenticationSession,
|
|
97
97
|
project: ResourceDescriptor,
|
|
98
|
-
options?:
|
|
98
|
+
options?: IssuesForProjectOptions,
|
|
99
99
|
): Promise<IssueShape[] | undefined> {
|
|
100
100
|
return (await this.getProviderIssuesForProjectWithTruncation(session, project, options))?.values;
|
|
101
101
|
}
|
|
@@ -103,7 +103,7 @@ export class TrelloIntegration extends IssuesIntegration<IssuesCloudHostIntegrat
|
|
|
103
103
|
protected override async getProviderIssuesForProjectWithTruncation(
|
|
104
104
|
session: ProviderAuthenticationSession,
|
|
105
105
|
project: ResourceDescriptor,
|
|
106
|
-
options?:
|
|
106
|
+
options?: IssuesForProjectOptions,
|
|
107
107
|
): Promise<{ values: IssueShape[]; truncated: boolean; metadata?: CollectionMetadata } | undefined> {
|
|
108
108
|
// A non-issue descriptor genuinely has nothing to read (empty), but a missing app key is a broken read.
|
|
109
109
|
if (!isIssueResourceDescriptor(project)) return undefined;
|
|
@@ -129,6 +129,7 @@ export class TrelloIntegration extends IssuesIntegration<IssuesCloudHostIntegrat
|
|
|
129
129
|
const result = await api.getTrelloIssuesForBoard(tokenWithInfo, appKey, project.id, {
|
|
130
130
|
assigneeLogins: options?.user != null ? [options.user] : undefined,
|
|
131
131
|
trelloBoardListsById: trelloBoardListsById,
|
|
132
|
+
sort: options?.sort,
|
|
132
133
|
});
|
|
133
134
|
|
|
134
135
|
const values = result.values.flatMap(issue => {
|
|
@@ -6,7 +6,7 @@ import type {
|
|
|
6
6
|
} from '@gitkraken/provider-apis';
|
|
7
7
|
import { isCancellationError } from '../../../../utils/cancellation.js';
|
|
8
8
|
import { uniqueBy } from '../../../../utils/iterable.js';
|
|
9
|
-
import { toCollectionScopeFailure } from '../../collectionMetadata.js';
|
|
9
|
+
import { throwIfCallerContractError, toCollectionScopeFailure } from '../../collectionMetadata.js';
|
|
10
10
|
import { collectionScopeKey } from '../../results.js';
|
|
11
11
|
import type { ProviderApiPagedResult, ProviderHierarchyResult } from '../models.js';
|
|
12
12
|
|
|
@@ -144,6 +144,11 @@ export async function collectProviderPagedResult<T>(
|
|
|
144
144
|
} catch (ex) {
|
|
145
145
|
if (isCancellationError(ex)) throw ex;
|
|
146
146
|
|
|
147
|
+
// A caller-contract error is not a fact about this scope, so it is never recorded as one — see
|
|
148
|
+
// `throwIfCallerContractError`. Checked alongside cancellation because both are errors that a
|
|
149
|
+
// per-scope failure would misdescribe.
|
|
150
|
+
throwIfCallerContractError(ex);
|
|
151
|
+
|
|
147
152
|
// When the caller supplied a scope, preserve the items already fetched from that scope and record the
|
|
148
153
|
// failure in collection metadata rather than re-throwing and discarding the prefix. Callers without a
|
|
149
154
|
// scope keep the legacy throw behavior.
|
|
@@ -33,6 +33,12 @@ import { gitHostOnlySurfaceWarning, issuesUnsupportedWarning, noConnectionWarnin
|
|
|
33
33
|
* `includeAllAssignees: true`, which resolves to no assignee constraint at all, so unassigned issues ARE
|
|
34
34
|
* included. The equivalent is an OMITTED `relationships`, not `['any-assignee']`: `assignee:*` means "has some
|
|
35
35
|
* assignee" and would silently exclude every unassigned issue, which is the opposite of broadening.
|
|
36
|
+
*
|
|
37
|
+
* Takes no `sort`, unlike `listIssuesPage` and `searchIssuesPage`. One logical page here spans several orgs, each
|
|
38
|
+
* at its own provider position in a cursor bundle, so honoring an order across them would need a k-way merge with
|
|
39
|
+
* a buffer per org rather than a sort of what arrived — the page is a slice of several independent walks, not a
|
|
40
|
+
* union of one round's results. `searchIssuesPage({ repos, criteria: { sort } })` answers the ordered version of
|
|
41
|
+
* this question for a caller that knows its repositories, and is already the recommended migration above.
|
|
36
42
|
*/
|
|
37
43
|
|
|
38
44
|
export interface BroadenIssuesOptions {
|
|
@@ -44,7 +44,14 @@ export interface IssueCountScope {
|
|
|
44
44
|
/** Repositories to count over. Combines with `org`, exactly as in `searchIssuesPage`. */
|
|
45
45
|
repos?: ProviderReposInput;
|
|
46
46
|
org?: string;
|
|
47
|
-
/**
|
|
47
|
+
/**
|
|
48
|
+
* Same criteria model as `searchIssuesPage`, validated against the same capability table.
|
|
49
|
+
*
|
|
50
|
+
* `criteria.sort` does not affect the count — a total is invariant under ordering — but it is still VALIDATED,
|
|
51
|
+
* and an unsupported key refuses this scope exactly as it would refuse the read. That is the point of the
|
|
52
|
+
* count: it previews the constraints the read will apply, so one that accepted what the read refuses would
|
|
53
|
+
* promise a fetch that can't happen, which is worse than no preview at all.
|
|
54
|
+
*/
|
|
48
55
|
criteria?: IssueSearchCriteria;
|
|
49
56
|
}
|
|
50
57
|
|
|
@@ -4,6 +4,7 @@ import type {
|
|
|
4
4
|
IssueSearchCapabilities,
|
|
5
5
|
IssueSearchCriteria,
|
|
6
6
|
IssueSearchRelationship,
|
|
7
|
+
IssueSorting,
|
|
7
8
|
PullRequestFilter,
|
|
8
9
|
PullRequestSearchCapabilities,
|
|
9
10
|
PullRequestSearchCriteria,
|
|
@@ -237,6 +238,12 @@ export function resolveIssueSearchCriteria(
|
|
|
237
238
|
if (criteria.state != null && criteria.state !== 'open' && !supported.states) {
|
|
238
239
|
unsupported.push('state');
|
|
239
240
|
}
|
|
241
|
+
// Folded into the same `unsupported-criteria` rejection rather than given its own reason, so a caller asking
|
|
242
|
+
// for one inexpressible filter and one inexpressible sort learns about both at once instead of fixing them one
|
|
243
|
+
// refusal at a time. The `sorts` list is `supported`'s own, so this needs no branch on which surface it is.
|
|
244
|
+
if (criteria.sort != null && !supported.sorts.includes(criteria.sort)) {
|
|
245
|
+
unsupported.push(`sort:${criteria.sort}`);
|
|
246
|
+
}
|
|
240
247
|
|
|
241
248
|
if (unsupported.length > 0) return { rejection: { reason: 'unsupported-criteria', criteria: unsupported } };
|
|
242
249
|
|
|
@@ -264,6 +271,7 @@ const unsupportedIssueSearchCapabilities: IssueSearchCapabilities = {
|
|
|
264
271
|
createdAfter: false,
|
|
265
272
|
withoutLinkedPullRequest: false,
|
|
266
273
|
states: false,
|
|
274
|
+
sorts: [],
|
|
267
275
|
};
|
|
268
276
|
|
|
269
277
|
/** What a provider with no filtered pull-request search reports. */
|
|
@@ -313,6 +321,57 @@ export function resolveIssueSearchScope(
|
|
|
313
321
|
return { rejection: 'unscoped' };
|
|
314
322
|
}
|
|
315
323
|
|
|
324
|
+
/**
|
|
325
|
+
* What {@link getSupportedFilters} reports: every vocabulary a provider's reads can express, so a consumer can
|
|
326
|
+
* narrow to it BEFORE issuing a read. See that function for the capability table itself and why intersecting
|
|
327
|
+
* against this is what keeps a filtered read from being refused.
|
|
328
|
+
*
|
|
329
|
+
* Named rather than written inline, because the same shape is the declared return type of THREE declarations that
|
|
330
|
+
* all describe one value — this function, `IntegrationService.getSupportedFilters`, which only forwards to it, and
|
|
331
|
+
* `IntegrationManager.getSupportedFilters`, which publishes it. Spelled out three times, a member added here
|
|
332
|
+
* reached one of them and left the others a compile error away from the truth; that is exactly how the two sort
|
|
333
|
+
* members below came to be written out three times.
|
|
334
|
+
*/
|
|
335
|
+
export type SupportedFilters = {
|
|
336
|
+
pullRequests: PullRequestFilter[];
|
|
337
|
+
pullRequestsAccountWide: PullRequestFilter[];
|
|
338
|
+
/**
|
|
339
|
+
* Criteria and scopes the filtered pull-request search can express. Always present; an empty relationship list
|
|
340
|
+
* means the provider exposes no filtered pull-request search.
|
|
341
|
+
*/
|
|
342
|
+
pullRequestSearch: PullRequestSearchCapabilities;
|
|
343
|
+
/**
|
|
344
|
+
* Filters the repo-scoped issue read accepts — and, for an issue tracker (Jira/Linear/Trello), its
|
|
345
|
+
* project-scoped read, that being its only issue surface. A tracker therefore reports here and leaves
|
|
346
|
+
* `issuesAccountWide` empty, so intersecting a tracker against that field would read "cannot filter" for a
|
|
347
|
+
* provider that filters fine.
|
|
348
|
+
*/
|
|
349
|
+
issues: IssueFilter[];
|
|
350
|
+
issuesAccountWide: IssueFilter[];
|
|
351
|
+
/**
|
|
352
|
+
* What the filtered issue search (and the count probe over the same criteria) can express. Always present: a
|
|
353
|
+
* provider with no filtered issue search reports an empty `relationships` and all-false flags, which is the
|
|
354
|
+
* signal to hide that surface rather than to hide individual chips.
|
|
355
|
+
*/
|
|
356
|
+
issueSearch: IssueSearchCapabilities;
|
|
357
|
+
/**
|
|
358
|
+
* Sort keys the repo-scoped issue read can express — and, for an issue tracker, its project-scoped read. Empty
|
|
359
|
+
* means the read can't be ordered, so pass no `sort`.
|
|
360
|
+
*
|
|
361
|
+
* A key here is expressible on ONE provider query. A page spanning several repositories or projects is a merge,
|
|
362
|
+
* and a merge can only order by what a normalized issue carries, so `priority`/`dueDate`/`resolved` are refused
|
|
363
|
+
* there even where they are listed. Read one scope at a time to use them.
|
|
364
|
+
*/
|
|
365
|
+
issueSorts: IssueSorting[];
|
|
366
|
+
/**
|
|
367
|
+
* Sort keys the account-wide issue read can express — a different vocabulary, not a subset: for GitLab the two
|
|
368
|
+
* reads are different APIs. Needs no mergeability caveat, because every account-wide read is a union of several
|
|
369
|
+
* queries, so only keys a merge can honor are listed at all. Empty for an issue tracker, which reports under
|
|
370
|
+
* `issueSorts`.
|
|
371
|
+
*/
|
|
372
|
+
issueSortsAccountWide: IssueSorting[];
|
|
373
|
+
};
|
|
374
|
+
|
|
316
375
|
/**
|
|
317
376
|
* The filters `listPullRequestsPage`/`listIssuesPage` (and the sweeps) accept for a provider, so a caller can
|
|
318
377
|
* narrow to what the provider can express BEFORE issuing the read.
|
|
@@ -345,19 +404,19 @@ export function resolveIssueSearchScope(
|
|
|
345
404
|
* `pullRequestSearch` describes the separate filtered PR search. Its table declares each criteria vocabulary
|
|
346
405
|
* plus repository/organization scope support; an empty relationship list means the search itself is absent.
|
|
347
406
|
*
|
|
407
|
+
* `issueSorts` / `issueSortsAccountWide` / `issueSearch.sorts` are the ORDERING vocabulary of those same three
|
|
408
|
+
* issue reads, split the same way and for the same reason (GitLab's repo-scoped read is GraphQL and its
|
|
409
|
+
* account-wide read is REST, with genuinely different sort vocabularies). Empty means the read can't be ordered,
|
|
410
|
+
* so pass no `sort`; a key not listed refuses the whole read exactly like an inexpressible filter. Note a key
|
|
411
|
+
* listed here is expressible on ONE provider query: a read that fans out across projects can only honor a key
|
|
412
|
+
* derivable from a normalized issue, so it refuses `priority`/`dueDate`/`resolved` on top of this table.
|
|
413
|
+
*
|
|
348
414
|
* Note this is a CAPABILITY table — "what the provider can express" — not a recommendation. A consumer
|
|
349
415
|
* matching another tool's behavior may deliberately pass fewer filters than are listed here (or none, where an
|
|
350
416
|
* already-scoped read would only be narrowed by them). Intersecting against this table is what keeps a
|
|
351
417
|
* filtered read from being refused; it isn't a directive to use every filter in it.
|
|
352
418
|
*/
|
|
353
|
-
export function getSupportedFilters(providerId: IntegrationIds): {
|
|
354
|
-
pullRequests: PullRequestFilter[];
|
|
355
|
-
pullRequestsAccountWide: PullRequestFilter[];
|
|
356
|
-
pullRequestSearch: PullRequestSearchCapabilities;
|
|
357
|
-
issues: IssueFilter[];
|
|
358
|
-
issuesAccountWide: IssueFilter[];
|
|
359
|
-
issueSearch: IssueSearchCapabilities;
|
|
360
|
-
} {
|
|
419
|
+
export function getSupportedFilters(providerId: IntegrationIds): SupportedFilters {
|
|
361
420
|
const metadata = providersMetadata[providerId];
|
|
362
421
|
const issueSearch = metadata?.supportedIssueSearch;
|
|
363
422
|
const pullRequestSearch = metadata?.supportedPullRequestSearch;
|
|
@@ -385,6 +444,9 @@ export function getSupportedFilters(providerId: IntegrationIds): {
|
|
|
385
444
|
...issueSearch,
|
|
386
445
|
// Copied, so mutating the result can't corrupt the metadata table.
|
|
387
446
|
relationships: [...(issueSearch?.relationships ?? [])],
|
|
447
|
+
sorts: [...(issueSearch?.sorts ?? [])],
|
|
388
448
|
},
|
|
449
|
+
issueSorts: [...(metadata?.supportedIssueSorts ?? [])],
|
|
450
|
+
issueSortsAccountWide: [...(metadata?.supportedAccountWideIssueSorts ?? [])],
|
|
389
451
|
};
|
|
390
452
|
}
|