@gitkraken/core-gitlens 0.11.1 → 0.12.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.
- package/CHANGELOG.md +28 -1
- package/dist/git/models/issue.d.ts +3 -1
- package/dist/git/models/issue.js.map +1 -1
- package/dist/git/utils/issue.utils.d.ts +3 -1
- package/dist/git/utils/issue.utils.js +5 -1
- package/dist/git/utils/issue.utils.js.map +1 -1
- package/dist/plus/integrations/models/gitHostIntegration.js +3 -1
- package/dist/plus/integrations/models/gitHostIntegration.js.map +1 -1
- package/dist/plus/integrations/models/integration.js +1 -1
- package/dist/plus/integrations/providers/azure/azure.js +3 -2
- package/dist/plus/integrations/providers/azure/azure.js.map +1 -1
- package/dist/plus/integrations/providers/azure/models.d.ts +27 -10
- package/dist/plus/integrations/providers/azure/models.js +39 -19
- package/dist/plus/integrations/providers/azure/models.js.map +1 -1
- package/dist/plus/integrations/providers/azure/workItemStateCategories.d.ts +19 -0
- package/dist/plus/integrations/providers/azure/workItemStateCategories.js +32 -0
- package/dist/plus/integrations/providers/azure/workItemStateCategories.js.map +1 -0
- package/dist/plus/integrations/providers/azureDevOps.js +5 -5
- package/dist/plus/integrations/providers/azureDevOps.js.map +1 -1
- package/dist/plus/integrations/providers/issueSorts.d.ts +0 -1
- package/dist/plus/integrations/providers/jira-server.js +11 -5
- package/dist/plus/integrations/providers/jira-server.js.map +1 -1
- package/dist/plus/integrations/providers/jira.d.ts +5 -2
- package/dist/plus/integrations/providers/jira.js +45 -30
- package/dist/plus/integrations/providers/jira.js.map +1 -1
- package/dist/plus/integrations/providers/jiraIssueByKey.d.ts +3 -4
- package/dist/plus/integrations/providers/jiraIssueByKey.js +3 -4
- package/dist/plus/integrations/providers/jiraIssueByKey.js.map +1 -1
- package/dist/plus/integrations/providers/linearIssuesEtag.d.ts +5 -5
- package/dist/plus/integrations/providers/linearIssuesEtag.js +6 -6
- package/dist/plus/integrations/providers/linearIssuesEtag.js.map +1 -1
- package/dist/plus/integrations/providers/models.d.ts +11 -1
- package/dist/plus/integrations/providers/models.js +9 -9
- package/dist/plus/integrations/providers/models.js.map +1 -1
- package/dist/plus/integrations/providers/providersApi.d.ts +30 -32
- package/dist/plus/integrations/providers/providersApi.js +149 -46
- package/dist/plus/integrations/providers/providersApi.js.map +1 -1
- package/dist/plus/integrations/providers/utils/jiraIssueDrains.d.ts +27 -15
- package/dist/plus/integrations/providers/utils/jiraIssueDrains.js +72 -10
- package/dist/plus/integrations/providers/utils/jiraIssueDrains.js.map +1 -1
- package/dist/plus/integrations/reads/cursors.js +1 -1
- package/dist/plus/integrations/reads/drains.d.ts +0 -1
- package/dist/plus/integrations/reads/hierarchy.js +2 -2
- package/dist/plus/integrations/reads/hierarchy.js.map +1 -1
- package/dist/plus/integrations/reads/hierarchy.utils.d.ts +13 -0
- package/dist/plus/integrations/reads/hierarchy.utils.js +26 -1
- package/dist/plus/integrations/reads/hierarchy.utils.js.map +1 -1
- package/dist/plus/integrations/reads/issueTracker.js +4 -4
- package/dist/plus/integrations/reads/issueTracker.js.map +1 -1
- package/dist/plus/integrations/reads/issues.js +1 -1
- package/dist/plus/integrations/results.d.ts +12 -2
- package/dist/plus/integrations/results.js.map +1 -1
- package/dist/plus/integrations/utils/integration.utils.d.ts +6 -1
- package/dist/plus/integrations/utils/integration.utils.js +8 -1
- package/dist/plus/integrations/utils/integration.utils.js.map +1 -1
- package/docs/integrations.md +49 -19
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,32 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.12.0] - 2026-10-16
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Adds `orgId` to `ProviderOrganization`: the parent's stable id where `org` is only its label. `listProjects` sets it on Jira projects (the site's id, or the Data Center instance's domain), which is what `listIssueTrackerIssuesPage` takes as `org` for Jira (plus/integrations)
|
|
14
|
+
- Adds `isTerminalIssueStateCategory`, whether an issue state category ends the issue: `DONE` or `CANCELED` (git)
|
|
15
|
+
- Adds the workflow state and its category to Azure DevOps work items (`providerState`, and `issueType` on the native point and search reads), with `Removed` reported as `CANCELED`. The category is read from the work item type's states endpoint (`api-version=6.0-preview.1`, which Azure DevOps Server 2020 requires) and cached per host, project, type and credential for 5 minutes (GKDEV-3655) (plus/integrations)
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- Changes `listProjects` to publish a Jira project's key as its `name`, where it published the display name, so the item names what the project reads take; the display name is no longer on the item (plus/integrations)
|
|
20
|
+
- Changes `listIssueTrackerIssuesPage`'s `org` and `project` to select Jira sites and projects only by their canonical key (a site's id, a project's key), no longer also by a site's label or a project's name or id: a remembered selection whose site or project was removed selected another one that carried the old value as a name or id. Linear and Trello still match any identifier (plus/integrations)
|
|
21
|
+
- Changes `IssueProviderState.category` to also be `CANCELED`, for abandoned work (canceled, duplicate, removed): `toIssueShape` and `fromProviderIssue` close it as they close `DONE`. Linear's canceled and duplicate states now report `CANCELED` where they reported `DONE`, so a consumer that tests `category === 'DONE'` for a closed issue should test `isTerminalIssueStateCategory` instead (git, plus/integrations)
|
|
22
|
+
- Changes a user-scoped Jira Cloud read of a single project to read that project on its own instead of through the multi-project search, at the same cost, so a failure partway through its pages is attributed to the project rather than only to the site, and its truncation is reported per project (plus/integrations)
|
|
23
|
+
- Changes Azure DevOps work items to close by their state's category as well as their closed date, on the full reads and the cheap etag check alike: a work item in a `Completed`, `Resolved` or `Removed` state with no closed date now reads closed, and its etag changes once. Every work item read now needs its type's states: when that read fails, a project list keeps its rows (the failed type's without a category) as a partial collection with a failure scoped to the project, while a read by id (`getIssuesBatch`) and the cheap etag check fail. A project list keeps only the work items in the states it asked for: provider-apis selects open ones by their dates, so a `Removed` work item with no closed or resolved date is now left out of an open list rather than listed closed, and a closed-only list still doesn't select it. The native work item path asks for the states endpoint with the same `api-version`. Snapshots cached before this change carry no category and can't be reclassified until they are refreshed (GKDEV-3655) (plus/integrations)
|
|
24
|
+
- Changes Jira Data Center projects to carry their project key, which `listProjects` publishes as `name` and `listIssueTrackerIssuesPage` selects by, where they carried the display name (provider-apis now reports the key of `/rest/api/2/project`, GKDEV-3654); a project without one falls back to its numeric id. A Data Center project selection saved as its display name must be picked again, and a page cursor from before this change is best restarted: it re-reads the projects it had completed and no longer recognizes the ones it was retrying (plus/integrations)
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
|
|
28
|
+
- Fixes Jira and Jira Data Center issues in a done status category reading as open (`closed: false`, `state: 'opened'`) on every read but the batch read by key, with no `providerState.category`, so a closed lookup missed them and an open one returned them (gitkraken/kepler#4010). `@gitkraken/provider-apis` 0.65.1 maps the category from the status category's stable `key` rather than its localized `name`, and no longer reads an unrecognized one as `DONE` (GKDEV-3656), so `toIssueShape` now trusts it for Jira as for every other tracker: an issue closes when its category is `done`, and stays open in any other, Jira's "No Category" included, whatever language the instance uses. Every Jira read now reports `providerState.category`, and a Jira Data Center issue in a done category changes its `getIssuesBatch` etag once (plus/integrations)
|
|
29
|
+
- Fixes Jira and Jira Data Center searches failing a whole page when one issue's type hides a field such as Fix versions or Comment, so Stories and Sub-tasks vanished from issue lists while Epics showed: such an issue is now read, one that still can't be read is dropped and reported (next entry) instead of failing its page, and a page whose every issue is unreadable comes back partial instead of ending the drain. By bumping `@gitkraken/provider-apis` to 0.65.0, which also brings the Linear and Jira Data Center changes above (GKDEV-3652, GKDEV-3653) (plus/integrations)
|
|
30
|
+
- Fixes Jira and Jira Data Center issue reads discarding the collection metadata of each search page, so an issue `@gitkraken/provider-apis` drops because it can't read it (GKDEV-3652, e.g. one whose type hides a field the normalizer needed) vanished with no warning. Project reads (`listIssueTrackerIssuesPage`, `IssuesIntegration.getIssuesForProject*`) keep its siblings and now report the drop as a `provider` failure scoped to its project: `fetchFailed`, a warning, and the project `truncated` with recovery `none`. A user-scoped search across projects that hits one is read project by project; on Jira Data Center a search that names a single project is read as that project from the start, so a dropped issue costs no second read. A run of pages that dropped issues is reported once per scope, naming the first page's keys and how many more pages dropped issues, rather than once per page. A page whose every issue was unreadable no longer loses its failure to a later page error, and a project read the page backstop stopped after such a page also reports the backstop. `searchMyIssuesWithTruncationResult` (account-wide, which no facade read reaches for these trackers) carries the same metadata on both hosts; on Jira Cloud each site is drained on its own, so a site whose read failed keeps what it read and is reported as that site's failure (a refused one going through the scoped auth check) instead of being only logged, and a site the page backstop stopped makes the read `truncated`. The metadata comes from `@gitkraken/provider-apis` 0.65.0 ([#5992](https://github.com/gitkraken/vscode-gitlens/issues/5992)) (plus/integrations)
|
|
31
|
+
- Fixes Jira Cloud's per-project issue read addressing the project by its display name, which JQL resolves against project keys first, so a project named like another project's key read that project's issues; it now reads by key, as the multi-project search does, and attributes its failures to the key (plus/integrations)
|
|
32
|
+
- Fixes Azure DevOps repository-scoped issue reads (`listIssuesPage({ repos })`, `getMyIssuesForRepos`) dropping a project read's own collection metadata and truncation, so a project read that came back incomplete was reported as complete (plus/integrations)
|
|
33
|
+
- Fixes the Linear cheap etag check treating a `duplicate` issue as open while the full read closes it, which made the two compute different etags (plus/integrations)
|
|
34
|
+
|
|
9
35
|
## [0.11.1] - 2026-10-16
|
|
10
36
|
|
|
11
37
|
### Added
|
|
@@ -649,7 +675,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
|
|
|
649
675
|
|
|
650
676
|
- Initial release. Bundles `@gitlens/utils`, `@gitlens/git`, `@gitlens/git-cli`, `@gitlens/ai`, and `@gitlens/git-github` into a single core npm package with subpath exports.
|
|
651
677
|
|
|
652
|
-
[unreleased]: https://github.com/gitkraken/vscode-gitlens/compare/releases/core/v0.
|
|
678
|
+
[unreleased]: https://github.com/gitkraken/vscode-gitlens/compare/releases/core/v0.12.0...HEAD
|
|
679
|
+
[0.12.0]: https://github.com/gitkraken/vscode-gitlens/compare/releases/core/v0.11.1...gitkraken:releases/core/v0.12.0
|
|
653
680
|
[0.11.1]: https://github.com/gitkraken/vscode-gitlens/compare/releases/core/v0.11.0...gitkraken:releases/core/v0.11.1
|
|
654
681
|
[0.11.0]: https://github.com/gitkraken/vscode-gitlens/compare/releases/core/v0.10.7...gitkraken:releases/core/v0.11.0
|
|
655
682
|
[0.10.7]: https://github.com/gitkraken/vscode-gitlens/compare/releases/core/v0.10.6...gitkraken:releases/core/v0.10.7
|
|
@@ -269,7 +269,9 @@ export type IssueProviderState = {
|
|
|
269
269
|
id?: string;
|
|
270
270
|
name: string;
|
|
271
271
|
color?: string;
|
|
272
|
-
|
|
272
|
+
/** The provider's workflow category. `CANCELED` is abandoned work (Linear's canceled and duplicate states, Azure's
|
|
273
|
+
* `Removed` category): closed like `DONE`, kept apart so a consumer can tell the two outcomes apart. */
|
|
274
|
+
category?: 'TO_DO' | 'IN_PROGRESS' | 'DONE' | 'CANCELED';
|
|
273
275
|
};
|
|
274
276
|
export interface IssueProject {
|
|
275
277
|
id: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"issue.js","names":[],"sources":["../../../../git/src/models/issue.ts"],"sourcesContent":["import { loggable } from '@gitlens/utils/decorators/log.js';\nimport type { RequireSome, RequireSomeWithProps } from '@gitlens/utils/types.js';\nimport type { IssueOrPullRequest, IssueOrPullRequestState } from './issueOrPullRequest.js';\nimport type { ProviderReference } from './remoteProvider.js';\nimport type { RepositoryIdentityDescriptor } from './repositoryIdentities.js';\n\n/** Selects which issue states a read should include. `all` covers open + closed. */\nexport type IssueStateFilter = 'open' | 'closed' | 'all';\n\n/**\n * One relationship a filtered issue search can constrain on.\n *\n * The last two are USER-INDEPENDENT — they describe the issue, not the caller — and neither is a SCOPE: either\n * one alone matches every such issue on the host, so a search using one still needs a repository/org scope.\n */\nexport type IssueSearchRelationship =\n\t/** Authored by the current user. */\n\t| 'authored'\n\t/** Assigned to the current user. */\n\t| 'assigned'\n\t/** Mentions the current user. */\n\t| 'mentioned'\n\t/** Assigned to ANYONE. Excludes unassigned issues — see {@link IssueSearchCriteria.relationships}. */\n\t| 'any-assignee'\n\t/** Assigned to nobody. The complement of `any-assignee`, not a broadening of it. */\n\t| 'unassigned';\n\n/**\n * A field an issue read can be ordered by, provider-neutral. No provider expresses all of them: each read\n * validates the requested key against the capability its provider declares and refuses one it can't express\n * server-side, rather than serving a differently-ordered list under the name of the one that was asked for.\n *\n * `closed` and `resolved` are deliberately SEPARATE, not two names for the same date. Azure DevOps tracks both\n * and they differ (an issue can be closed without being resolved and resolved without being closed), and Jira\n * has no close date at all — it models the equivalent as `resolutiondate`. Collapsing them would force one of\n * those two providers to lie about which date it ordered by.\n */\nexport type IssueSortField =\n\t/** Creation date. */\n\t| 'created'\n\t/** Last activity. */\n\t| 'updated'\n\t/** Close date. Only where the provider orders by it server-side — notably NOT GitHub. */\n\t| 'closed'\n\t/** Resolution date (Jira `resolutiondate`, Azure `ResolvedDate`). Distinct from `closed`. */\n\t| 'resolved'\n\t/** Number of comments. */\n\t| 'comments'\n\t/** Reactions/upvotes. */\n\t| 'reactions'\n\t/** The provider's own priority field. */\n\t| 'priority'\n\t/** Due date. */\n\t| 'dueDate'\n\t/** Alphabetical by title. */\n\t| 'title';\n\n/**\n * How an issue read is ordered, as `field:direction` — the same shape `BranchSorting`/`TagSorting` already use,\n * so it is one serializable string a consumer can persist, compare, or bind straight to a setting or a dropdown.\n */\nexport type IssueSorting = `${IssueSortField}:asc` | `${IssueSortField}:desc`;\n\n/**\n * The order every issue read that HAS a default applies when the caller asks for none: most recently updated\n * first, which is what those reads served before ordering was an option.\n *\n * One definition rather than one per layer, because it is a promise made in several places at once — the criteria\n * model documents it, the GitHub query emits it, and the result-ceiling warning quotes it — and three copies would\n * be free to disagree about what \"the default\" is.\n *\n * Note it is not a default every read has, and the two layers differ. The API client's account-wide \"my issues\"\n * search (`GitHubApi.searchMyIssues`) never requested an order, so a direct caller omitting `sort` still gets\n * GitHub's relevance order — the default is opt-in there, to keep that read's already-shipped results unchanged.\n * The FACADE does apply it: GitHub declares `updated:desc` among its account-wide keys, so\n * `readAccountWideIssuesPage` resolves the omission to this default and forwards it, and that read's emitted query\n * gained a `sort:updated` qualifier it did not have before. A read whose surface cannot express even this key is\n * the only one the facade leaves in the provider's own order.\n */\nexport const defaultIssueSort: IssueSorting = 'updated:desc';\n\n/**\n * What a filtered issue search narrows on: a provider-neutral criteria set, translated to each provider's own\n * query language by its integration.\n *\n * Structured rather than a provider query string so a consumer can render filter chips and hide the ones a\n * provider can't express, and so the same criteria mean the same thing on a provider whose query language looks\n * nothing like GitHub's search syntax. Every field is validated against the provider's declared capability\n * BEFORE the read runs, all-or-nothing: a criterion the provider can't express server-side refuses the whole\n * read rather than serving a list that was never narrowed. Client-side narrowing is not an option — the dropped\n * items still counted toward the page and cursor the provider produced, so a post-filter would leave the items\n * describing a different result set than the paging that came with them.\n */\nexport interface IssueSearchCriteria {\n\t/**\n\t * Relationships to constrain on, OR-ed together (each becomes its own provider query, unioned and deduped).\n\t * Omitted means NO relationship constraint at all — every issue in scope, assigned or not — which requires a\n\t * repository/org scope.\n\t *\n\t * `any-assignee` and `unassigned` partition the scope between them and are mutually exclusive; passing both is\n\t * refused rather than silently dropping one. Note that \"all visible issues\" is the OMITTED case, NOT\n\t * `any-assignee`, which excludes unassigned issues.\n\t */\n\trelationships?: IssueSearchRelationship[];\n\t/**\n\t * Free text, matched by the provider's own relevance rules — NOT a substring match, and not a way to smuggle\n\t * qualifiers: a token that would read as one is dropped, as are quotes and control characters, so text can\n\t * never re-scope the search. The structured criteria are the qualifier channel.\n\t */\n\ttext?: string;\n\t/** Issue states to include. Omitted reads open issues only. */\n\tstate?: IssueStateFilter;\n\t/** Labels the issue must carry — AND-ed, matching GitHub's own `label:` semantics. */\n\tlabels?: string[];\n\tmilestone?: string;\n\t/** ISO date (`YYYY-MM-DD`). The most effective narrowing criterion by far on a large scope. */\n\tupdatedAfter?: string;\n\t/** ISO date (`YYYY-MM-DD`). */\n\tcreatedAfter?: string;\n\t/** Issues with no linked pull request. */\n\twithoutLinkedPullRequest?: boolean;\n\t/** Includes issues in archived repositories, which are excluded by default. */\n\tincludeArchived?: boolean;\n\t/**\n\t * How to order the results. Omitted means `updated:desc`, which is what this search has always served.\n\t *\n\t * Validated like every other criterion — all-or-nothing against {@link IssueSearchCapabilities.sorts}: a key\n\t * the provider can't express server-side refuses the WHOLE read rather than falling back to the default.\n\t * Serving another order is not a smaller error than serving a wider result: combined with the provider's\n\t * result ceiling it returns a different subset than was asked for, and the paging that comes with it describes\n\t * that other subset.\n\t *\n\t * Do not change it mid-pagination. A cursor carries the sort it was produced under, and threading it under a\n\t * different key is refused rather than serving a sequence with gaps and repeats: drop the cursor instead.\n\t */\n\tsort?: IssueSorting;\n}\n\n/**\n * Which {@link IssueSearchCriteria} fields a provider's filtered issue search can express server-side.\n *\n * An empty `relationships` with every flag false means the provider has NO filtered issue search — the read is\n * refused outright, so a consumer should offer neither the surface nor its chips.\n */\nexport interface IssueSearchCapabilities {\n\t/** Relationships the search can constrain on. Empty means the search itself is unsupported. */\n\trelationships: IssueSearchRelationship[];\n\ttext: boolean;\n\tlabels: boolean;\n\tmilestone: boolean;\n\tupdatedAfter: boolean;\n\tcreatedAfter: boolean;\n\twithoutLinkedPullRequest: boolean;\n\t/** Whether {@link IssueSearchCriteria.state} can select anything other than the provider's default (open). */\n\tstates: boolean;\n\t/**\n\t * Sort keys the search can express IN SERVER. Always contains at least `updated:desc` — the historical default\n\t * — when the search exists at all, so it is never empty for a usable surface; a provider without a filtered\n\t * search reports an empty `relationships`, which is already the signal that there is no surface to order.\n\t */\n\tsorts: IssueSorting[];\n}\n\n/**\n * The read that produced an issue row, as a key for `getIssueFieldPresence` (`@gitlens/integrations`). It names a\n * READ, not a field set: the same tag can carry different fields on different providers.\n */\nexport type IssueProjection =\n\t/** A single-item read. */\n\t| 'point'\n\t/** The filtered search. */\n\t| 'search'\n\t/** The account-wide list, and the trackers' \"my issues\". */\n\t| 'account'\n\t/** A repository-scoped list. */\n\t| 'repos'\n\t/** A tracker project's issues (`listIssueTrackerIssuesPage`, `getIssuesForProject`). */\n\t| 'project'\n\t/** The batch read. */\n\t| 'batch';\n\nexport interface IssueShape extends IssueOrPullRequest {\n\t/** `undefined` when the provider can't resolve the author, e.g. a deleted GitHub account */\n\tauthor: IssueMember | undefined;\n\tassignees: IssueMember[];\n\t/** The provider's own workflow state, when it exposes one beyond the normalized open/closed state. */\n\tproviderState?: IssueProviderState;\n\trepository?: IssueRepository;\n\tlabels?: IssueLabel[];\n\tbody?: string;\n\t/**\n\t * The syntax used by `body`. When omitted, consumers should treat `body` as Markdown — except that Azure DevOps\n\t * work items and Bitbucket Cloud issues carry HTML with no `bodyFormat` set.\n\t */\n\tbodyFormat?: IssueBodyFormat;\n\tproject?: IssueProject;\n\tissueType?: string;\n\t/** An issue can belong to several Jira sprints; Azure reports one iteration. */\n\titerations?: IssueIteration[];\n\t/** The read that produced this row. Absent means unknown: a legacy row, or a provider or read not yet tagged. */\n\treadonly projection?: IssueProjection;\n}\n\n@loggable(i => i.id)\nexport class Issue implements IssueShape {\n\treadonly type = 'issue';\n\n\tconstructor(\n\t\tpublic readonly provider: ProviderReference,\n\t\tpublic readonly id: string,\n\t\tpublic readonly nodeId: string | undefined,\n\t\tpublic readonly title: string,\n\t\tpublic readonly url: string,\n\t\tpublic readonly createdDate: Date,\n\t\tpublic readonly updatedDate: Date,\n\t\tpublic readonly closed: boolean,\n\t\tpublic readonly state: IssueOrPullRequestState,\n\t\tpublic readonly author: IssueMember | undefined,\n\t\tpublic readonly assignees: IssueMember[],\n\t\tpublic readonly repository?: IssueRepository,\n\t\tpublic readonly closedDate?: Date,\n\t\tpublic readonly labels?: IssueLabel[],\n\t\tpublic readonly commentsCount?: number,\n\t\tpublic readonly thumbsUpCount?: number,\n\t\tpublic readonly body?: string,\n\t\tpublic readonly project?: IssueProject,\n\t\tpublic readonly number?: string,\n\t\tpublic readonly issueType?: string,\n\t\tpublic readonly providerState?: IssueProviderState,\n\t\tpublic readonly bodyFormat?: IssueBodyFormat,\n\t\tpublic readonly iterations?: IssueIteration[],\n\t\tpublic readonly projection?: IssueProjection,\n\t) {}\n\n\tstatic is(issue: unknown): issue is Issue {\n\t\treturn issue instanceof Issue;\n\t}\n}\n\nexport type IssueBodyFormat = 'markdown' | 'jira-wiki';\n\nexport const enum RepositoryAccessLevel {\n\tAdmin = 100,\n\tMaintain = 40,\n\tWrite = 30,\n\tTriage = 20,\n\tRead = 10,\n\tNone = 0,\n}\n\nexport interface IssueLabel {\n\tcolor?: string;\n\tname: string;\n}\n\n/**\n * Sprint metadata is optional because some providers only report an iteration path. An absent `isActive`\n * means unknown, not inactive, so consumers must not use it to exclude those iterations by default.\n */\nexport interface IssueIteration {\n\t/**\n\t * A sprint id on Jira, the verbatim iteration path on Azure — so it is only meaningful within the provider's\n\t * project, never across providers. Unique at read time but NOT durable: Azure rewrites the path when an\n\t * iteration node is renamed or re-parented, so don't persist it as a long-lived id.\n\t */\n\tid: string;\n\tname: string;\n\tisActive?: boolean;\n\tstartDate?: Date;\n\tendDate?: Date;\n}\n\nexport interface IssueMember {\n\tid: string;\n\t/**\n\t * Absent when the provider exposes no display name for the member. Optional on purpose: a fallback string\n\t * invented here (`'unknown'`, `''`) can't be told apart from a real name downstream, so it can't be undone by a\n\t * consumer that needs to render something else — or nothing at all, as when the member feeds an AI prompt.\n\t * Each consumer picks its own presentation.\n\t */\n\tname?: string;\n\t/** The provider's handle for this person, when it has one — GitHub's login, Azure's `uniqueName` (a UPN,\n\t * so an email), Bitbucket's mutable `nickname`. Display/labelling only: it is neither guaranteed present\n\t * (GitLab's native mapper has none) nor a stable identity, so never key a match off it. */\n\tusername?: string;\n\tavatarUrl?: string;\n\turl?: string;\n}\n\nexport type IssueProviderState = {\n\tid?: string;\n\tname: string;\n\tcolor?: string;\n\tcategory?: 'TO_DO' | 'IN_PROGRESS' | 'DONE';\n};\n\nexport interface IssueProject {\n\tid: string;\n\tname: string;\n\tresourceId: string;\n\tresourceName: string;\n}\n\nexport interface IssueRepository {\n\towner: string;\n\trepo: string;\n\taccessLevel?: RepositoryAccessLevel;\n\turl?: string;\n\tid?: string;\n}\n\nexport type IssueRepositoryIdentityDescriptor = RequireSomeWithProps<\n\tRequireSome<RepositoryIdentityDescriptor<string>, 'provider'>,\n\t'provider',\n\t'id' | 'domain' | 'repoDomain' | 'repoName'\n> &\n\tRequireSomeWithProps<RequireSome<RepositoryIdentityDescriptor<string>, 'remote'>, 'remote', 'domain'>;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA+EA,MAAa,mBAAiC;AA6HvC,IAAM,QAAA,SAAN,MAAM,MAA4B;CAIvB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CA1BjB,OAAgB;CAEhB,YACC,UACA,IACA,QACA,OACA,KACA,aACA,aACA,QACA,OACA,QACA,WACA,YACA,YACA,QACA,eACA,eACA,MACA,SACA,QACA,WACA,eACA,YACA,YACA,YACC;EAxBe,KAAA,WAAA;EACA,KAAA,KAAA;EACA,KAAA,SAAA;EACA,KAAA,QAAA;EACA,KAAA,MAAA;EACA,KAAA,cAAA;EACA,KAAA,cAAA;EACA,KAAA,SAAA;EACA,KAAA,QAAA;EACA,KAAA,SAAA;EACA,KAAA,YAAA;EACA,KAAA,aAAA;EACA,KAAA,aAAA;EACA,KAAA,SAAA;EACA,KAAA,gBAAA;EACA,KAAA,gBAAA;EACA,KAAA,OAAA;EACA,KAAA,UAAA;EACA,KAAA,SAAA;EACA,KAAA,YAAA;EACA,KAAA,gBAAA;EACA,KAAA,aAAA;EACA,KAAA,aAAA;EACA,KAAA,aAAA;CACd;CAEH,OAAO,GAAG,OAAgC;EACzC,OAAO,iBAAA;CACR;AACD;AAlCC,QAAA,SAAA,WAAA,CAAA,UAAS,MAAK,EAAE,EAAE,CAAA,GAAA,KAAA;AAsCnB,IAAkB,wBAAX,yBAAA,uBAAA;CACN,sBAAA,sBAAA,WAAA,OAAA;CACA,sBAAA,sBAAA,cAAA,MAAA;CACA,sBAAA,sBAAA,WAAA,MAAA;CACA,sBAAA,sBAAA,YAAA,MAAA;CACA,sBAAA,sBAAA,UAAA,MAAA;CACA,sBAAA,sBAAA,UAAA,KAAA;;AACD,EAAA,CAAA,CAAA"}
|
|
1
|
+
{"version":3,"file":"issue.js","names":[],"sources":["../../../../git/src/models/issue.ts"],"sourcesContent":["import { loggable } from '@gitlens/utils/decorators/log.js';\nimport type { RequireSome, RequireSomeWithProps } from '@gitlens/utils/types.js';\nimport type { IssueOrPullRequest, IssueOrPullRequestState } from './issueOrPullRequest.js';\nimport type { ProviderReference } from './remoteProvider.js';\nimport type { RepositoryIdentityDescriptor } from './repositoryIdentities.js';\n\n/** Selects which issue states a read should include. `all` covers open + closed. */\nexport type IssueStateFilter = 'open' | 'closed' | 'all';\n\n/**\n * One relationship a filtered issue search can constrain on.\n *\n * The last two are USER-INDEPENDENT — they describe the issue, not the caller — and neither is a SCOPE: either\n * one alone matches every such issue on the host, so a search using one still needs a repository/org scope.\n */\nexport type IssueSearchRelationship =\n\t/** Authored by the current user. */\n\t| 'authored'\n\t/** Assigned to the current user. */\n\t| 'assigned'\n\t/** Mentions the current user. */\n\t| 'mentioned'\n\t/** Assigned to ANYONE. Excludes unassigned issues — see {@link IssueSearchCriteria.relationships}. */\n\t| 'any-assignee'\n\t/** Assigned to nobody. The complement of `any-assignee`, not a broadening of it. */\n\t| 'unassigned';\n\n/**\n * A field an issue read can be ordered by, provider-neutral. No provider expresses all of them: each read\n * validates the requested key against the capability its provider declares and refuses one it can't express\n * server-side, rather than serving a differently-ordered list under the name of the one that was asked for.\n *\n * `closed` and `resolved` are deliberately SEPARATE, not two names for the same date. Azure DevOps tracks both\n * and they differ (an issue can be closed without being resolved and resolved without being closed), and Jira\n * has no close date at all — it models the equivalent as `resolutiondate`. Collapsing them would force one of\n * those two providers to lie about which date it ordered by.\n */\nexport type IssueSortField =\n\t/** Creation date. */\n\t| 'created'\n\t/** Last activity. */\n\t| 'updated'\n\t/** Close date. Only where the provider orders by it server-side — notably NOT GitHub. */\n\t| 'closed'\n\t/** Resolution date (Jira `resolutiondate`, Azure `ResolvedDate`). Distinct from `closed`. */\n\t| 'resolved'\n\t/** Number of comments. */\n\t| 'comments'\n\t/** Reactions/upvotes. */\n\t| 'reactions'\n\t/** The provider's own priority field. */\n\t| 'priority'\n\t/** Due date. */\n\t| 'dueDate'\n\t/** Alphabetical by title. */\n\t| 'title';\n\n/**\n * How an issue read is ordered, as `field:direction` — the same shape `BranchSorting`/`TagSorting` already use,\n * so it is one serializable string a consumer can persist, compare, or bind straight to a setting or a dropdown.\n */\nexport type IssueSorting = `${IssueSortField}:asc` | `${IssueSortField}:desc`;\n\n/**\n * The order every issue read that HAS a default applies when the caller asks for none: most recently updated\n * first, which is what those reads served before ordering was an option.\n *\n * One definition rather than one per layer, because it is a promise made in several places at once — the criteria\n * model documents it, the GitHub query emits it, and the result-ceiling warning quotes it — and three copies would\n * be free to disagree about what \"the default\" is.\n *\n * Note it is not a default every read has, and the two layers differ. The API client's account-wide \"my issues\"\n * search (`GitHubApi.searchMyIssues`) never requested an order, so a direct caller omitting `sort` still gets\n * GitHub's relevance order — the default is opt-in there, to keep that read's already-shipped results unchanged.\n * The FACADE does apply it: GitHub declares `updated:desc` among its account-wide keys, so\n * `readAccountWideIssuesPage` resolves the omission to this default and forwards it, and that read's emitted query\n * gained a `sort:updated` qualifier it did not have before. A read whose surface cannot express even this key is\n * the only one the facade leaves in the provider's own order.\n */\nexport const defaultIssueSort: IssueSorting = 'updated:desc';\n\n/**\n * What a filtered issue search narrows on: a provider-neutral criteria set, translated to each provider's own\n * query language by its integration.\n *\n * Structured rather than a provider query string so a consumer can render filter chips and hide the ones a\n * provider can't express, and so the same criteria mean the same thing on a provider whose query language looks\n * nothing like GitHub's search syntax. Every field is validated against the provider's declared capability\n * BEFORE the read runs, all-or-nothing: a criterion the provider can't express server-side refuses the whole\n * read rather than serving a list that was never narrowed. Client-side narrowing is not an option — the dropped\n * items still counted toward the page and cursor the provider produced, so a post-filter would leave the items\n * describing a different result set than the paging that came with them.\n */\nexport interface IssueSearchCriteria {\n\t/**\n\t * Relationships to constrain on, OR-ed together (each becomes its own provider query, unioned and deduped).\n\t * Omitted means NO relationship constraint at all — every issue in scope, assigned or not — which requires a\n\t * repository/org scope.\n\t *\n\t * `any-assignee` and `unassigned` partition the scope between them and are mutually exclusive; passing both is\n\t * refused rather than silently dropping one. Note that \"all visible issues\" is the OMITTED case, NOT\n\t * `any-assignee`, which excludes unassigned issues.\n\t */\n\trelationships?: IssueSearchRelationship[];\n\t/**\n\t * Free text, matched by the provider's own relevance rules — NOT a substring match, and not a way to smuggle\n\t * qualifiers: a token that would read as one is dropped, as are quotes and control characters, so text can\n\t * never re-scope the search. The structured criteria are the qualifier channel.\n\t */\n\ttext?: string;\n\t/** Issue states to include. Omitted reads open issues only. */\n\tstate?: IssueStateFilter;\n\t/** Labels the issue must carry — AND-ed, matching GitHub's own `label:` semantics. */\n\tlabels?: string[];\n\tmilestone?: string;\n\t/** ISO date (`YYYY-MM-DD`). The most effective narrowing criterion by far on a large scope. */\n\tupdatedAfter?: string;\n\t/** ISO date (`YYYY-MM-DD`). */\n\tcreatedAfter?: string;\n\t/** Issues with no linked pull request. */\n\twithoutLinkedPullRequest?: boolean;\n\t/** Includes issues in archived repositories, which are excluded by default. */\n\tincludeArchived?: boolean;\n\t/**\n\t * How to order the results. Omitted means `updated:desc`, which is what this search has always served.\n\t *\n\t * Validated like every other criterion — all-or-nothing against {@link IssueSearchCapabilities.sorts}: a key\n\t * the provider can't express server-side refuses the WHOLE read rather than falling back to the default.\n\t * Serving another order is not a smaller error than serving a wider result: combined with the provider's\n\t * result ceiling it returns a different subset than was asked for, and the paging that comes with it describes\n\t * that other subset.\n\t *\n\t * Do not change it mid-pagination. A cursor carries the sort it was produced under, and threading it under a\n\t * different key is refused rather than serving a sequence with gaps and repeats: drop the cursor instead.\n\t */\n\tsort?: IssueSorting;\n}\n\n/**\n * Which {@link IssueSearchCriteria} fields a provider's filtered issue search can express server-side.\n *\n * An empty `relationships` with every flag false means the provider has NO filtered issue search — the read is\n * refused outright, so a consumer should offer neither the surface nor its chips.\n */\nexport interface IssueSearchCapabilities {\n\t/** Relationships the search can constrain on. Empty means the search itself is unsupported. */\n\trelationships: IssueSearchRelationship[];\n\ttext: boolean;\n\tlabels: boolean;\n\tmilestone: boolean;\n\tupdatedAfter: boolean;\n\tcreatedAfter: boolean;\n\twithoutLinkedPullRequest: boolean;\n\t/** Whether {@link IssueSearchCriteria.state} can select anything other than the provider's default (open). */\n\tstates: boolean;\n\t/**\n\t * Sort keys the search can express IN SERVER. Always contains at least `updated:desc` — the historical default\n\t * — when the search exists at all, so it is never empty for a usable surface; a provider without a filtered\n\t * search reports an empty `relationships`, which is already the signal that there is no surface to order.\n\t */\n\tsorts: IssueSorting[];\n}\n\n/**\n * The read that produced an issue row, as a key for `getIssueFieldPresence` (`@gitlens/integrations`). It names a\n * READ, not a field set: the same tag can carry different fields on different providers.\n */\nexport type IssueProjection =\n\t/** A single-item read. */\n\t| 'point'\n\t/** The filtered search. */\n\t| 'search'\n\t/** The account-wide list, and the trackers' \"my issues\". */\n\t| 'account'\n\t/** A repository-scoped list. */\n\t| 'repos'\n\t/** A tracker project's issues (`listIssueTrackerIssuesPage`, `getIssuesForProject`). */\n\t| 'project'\n\t/** The batch read. */\n\t| 'batch';\n\nexport interface IssueShape extends IssueOrPullRequest {\n\t/** `undefined` when the provider can't resolve the author, e.g. a deleted GitHub account */\n\tauthor: IssueMember | undefined;\n\tassignees: IssueMember[];\n\t/** The provider's own workflow state, when it exposes one beyond the normalized open/closed state. */\n\tproviderState?: IssueProviderState;\n\trepository?: IssueRepository;\n\tlabels?: IssueLabel[];\n\tbody?: string;\n\t/**\n\t * The syntax used by `body`. When omitted, consumers should treat `body` as Markdown — except that Azure DevOps\n\t * work items and Bitbucket Cloud issues carry HTML with no `bodyFormat` set.\n\t */\n\tbodyFormat?: IssueBodyFormat;\n\tproject?: IssueProject;\n\tissueType?: string;\n\t/** An issue can belong to several Jira sprints; Azure reports one iteration. */\n\titerations?: IssueIteration[];\n\t/** The read that produced this row. Absent means unknown: a legacy row, or a provider or read not yet tagged. */\n\treadonly projection?: IssueProjection;\n}\n\n@loggable(i => i.id)\nexport class Issue implements IssueShape {\n\treadonly type = 'issue';\n\n\tconstructor(\n\t\tpublic readonly provider: ProviderReference,\n\t\tpublic readonly id: string,\n\t\tpublic readonly nodeId: string | undefined,\n\t\tpublic readonly title: string,\n\t\tpublic readonly url: string,\n\t\tpublic readonly createdDate: Date,\n\t\tpublic readonly updatedDate: Date,\n\t\tpublic readonly closed: boolean,\n\t\tpublic readonly state: IssueOrPullRequestState,\n\t\tpublic readonly author: IssueMember | undefined,\n\t\tpublic readonly assignees: IssueMember[],\n\t\tpublic readonly repository?: IssueRepository,\n\t\tpublic readonly closedDate?: Date,\n\t\tpublic readonly labels?: IssueLabel[],\n\t\tpublic readonly commentsCount?: number,\n\t\tpublic readonly thumbsUpCount?: number,\n\t\tpublic readonly body?: string,\n\t\tpublic readonly project?: IssueProject,\n\t\tpublic readonly number?: string,\n\t\tpublic readonly issueType?: string,\n\t\tpublic readonly providerState?: IssueProviderState,\n\t\tpublic readonly bodyFormat?: IssueBodyFormat,\n\t\tpublic readonly iterations?: IssueIteration[],\n\t\tpublic readonly projection?: IssueProjection,\n\t) {}\n\n\tstatic is(issue: unknown): issue is Issue {\n\t\treturn issue instanceof Issue;\n\t}\n}\n\nexport type IssueBodyFormat = 'markdown' | 'jira-wiki';\n\nexport const enum RepositoryAccessLevel {\n\tAdmin = 100,\n\tMaintain = 40,\n\tWrite = 30,\n\tTriage = 20,\n\tRead = 10,\n\tNone = 0,\n}\n\nexport interface IssueLabel {\n\tcolor?: string;\n\tname: string;\n}\n\n/**\n * Sprint metadata is optional because some providers only report an iteration path. An absent `isActive`\n * means unknown, not inactive, so consumers must not use it to exclude those iterations by default.\n */\nexport interface IssueIteration {\n\t/**\n\t * A sprint id on Jira, the verbatim iteration path on Azure — so it is only meaningful within the provider's\n\t * project, never across providers. Unique at read time but NOT durable: Azure rewrites the path when an\n\t * iteration node is renamed or re-parented, so don't persist it as a long-lived id.\n\t */\n\tid: string;\n\tname: string;\n\tisActive?: boolean;\n\tstartDate?: Date;\n\tendDate?: Date;\n}\n\nexport interface IssueMember {\n\tid: string;\n\t/**\n\t * Absent when the provider exposes no display name for the member. Optional on purpose: a fallback string\n\t * invented here (`'unknown'`, `''`) can't be told apart from a real name downstream, so it can't be undone by a\n\t * consumer that needs to render something else — or nothing at all, as when the member feeds an AI prompt.\n\t * Each consumer picks its own presentation.\n\t */\n\tname?: string;\n\t/** The provider's handle for this person, when it has one — GitHub's login, Azure's `uniqueName` (a UPN,\n\t * so an email), Bitbucket's mutable `nickname`. Display/labelling only: it is neither guaranteed present\n\t * (GitLab's native mapper has none) nor a stable identity, so never key a match off it. */\n\tusername?: string;\n\tavatarUrl?: string;\n\turl?: string;\n}\n\nexport type IssueProviderState = {\n\tid?: string;\n\tname: string;\n\tcolor?: string;\n\t/** The provider's workflow category. `CANCELED` is abandoned work (Linear's canceled and duplicate states, Azure's\n\t * `Removed` category): closed like `DONE`, kept apart so a consumer can tell the two outcomes apart. */\n\tcategory?: 'TO_DO' | 'IN_PROGRESS' | 'DONE' | 'CANCELED';\n};\n\nexport interface IssueProject {\n\tid: string;\n\tname: string;\n\tresourceId: string;\n\tresourceName: string;\n}\n\nexport interface IssueRepository {\n\towner: string;\n\trepo: string;\n\taccessLevel?: RepositoryAccessLevel;\n\turl?: string;\n\tid?: string;\n}\n\nexport type IssueRepositoryIdentityDescriptor = RequireSomeWithProps<\n\tRequireSome<RepositoryIdentityDescriptor<string>, 'provider'>,\n\t'provider',\n\t'id' | 'domain' | 'repoDomain' | 'repoName'\n> &\n\tRequireSomeWithProps<RequireSome<RepositoryIdentityDescriptor<string>, 'remote'>, 'remote', 'domain'>;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA+EA,MAAa,mBAAiC;AA6HvC,IAAM,QAAA,SAAN,MAAM,MAA4B;CAIvB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CA1BjB,OAAgB;CAEhB,YACC,UACA,IACA,QACA,OACA,KACA,aACA,aACA,QACA,OACA,QACA,WACA,YACA,YACA,QACA,eACA,eACA,MACA,SACA,QACA,WACA,eACA,YACA,YACA,YACC;EAxBe,KAAA,WAAA;EACA,KAAA,KAAA;EACA,KAAA,SAAA;EACA,KAAA,QAAA;EACA,KAAA,MAAA;EACA,KAAA,cAAA;EACA,KAAA,cAAA;EACA,KAAA,SAAA;EACA,KAAA,QAAA;EACA,KAAA,SAAA;EACA,KAAA,YAAA;EACA,KAAA,aAAA;EACA,KAAA,aAAA;EACA,KAAA,SAAA;EACA,KAAA,gBAAA;EACA,KAAA,gBAAA;EACA,KAAA,OAAA;EACA,KAAA,UAAA;EACA,KAAA,SAAA;EACA,KAAA,YAAA;EACA,KAAA,gBAAA;EACA,KAAA,aAAA;EACA,KAAA,aAAA;EACA,KAAA,aAAA;CACd;CAEH,OAAO,GAAG,OAAgC;EACzC,OAAO,iBAAA;CACR;AACD;AAlCC,QAAA,SAAA,WAAA,CAAA,UAAS,MAAK,EAAE,EAAE,CAAA,GAAA,KAAA;AAsCnB,IAAkB,wBAAX,yBAAA,uBAAA;CACN,sBAAA,sBAAA,WAAA,OAAA;CACA,sBAAA,sBAAA,cAAA,MAAA;CACA,sBAAA,sBAAA,WAAA,MAAA;CACA,sBAAA,sBAAA,YAAA,MAAA;CACA,sBAAA,sBAAA,UAAA,MAAA;CACA,sBAAA,sBAAA,UAAA,KAAA;;AACD,EAAA,CAAA,CAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Issue, IssueRepositoryIdentityDescriptor, IssueShape, IssueSorting } from "../models/issue.js";
|
|
1
|
+
import { Issue, IssueProviderState, IssueRepositoryIdentityDescriptor, IssueShape, IssueSorting } from "../models/issue.js";
|
|
2
2
|
//#region ../git/src/utils/issue.utils.d.ts
|
|
3
3
|
/**
|
|
4
4
|
* The order a read that ALWAYS orders is being made under: the caller's key, or the facade's default.
|
|
@@ -46,5 +46,7 @@ export declare function getRepositoryIdentityForIssue(issue: IssueShape | Issue)
|
|
|
46
46
|
* report the viewer's access as fetched when the copy no longer has it.
|
|
47
47
|
*/
|
|
48
48
|
export declare function serializeIssue(value: IssueShape): IssueShape;
|
|
49
|
+
/** Whether a provider's workflow category ends the issue: done or abandoned (see {@link IssueProviderState.category}). */
|
|
50
|
+
export declare function isTerminalIssueStateCategory(category: IssueProviderState['category']): boolean;
|
|
49
51
|
//#endregion
|
|
50
52
|
//# sourceMappingURL=issue.utils.d.ts.map
|
|
@@ -164,7 +164,11 @@ function serializeIssue(value) {
|
|
|
164
164
|
}))
|
|
165
165
|
};
|
|
166
166
|
}
|
|
167
|
+
/** Whether a provider's workflow category ends the issue: done or abandoned (see {@link IssueProviderState.category}). */
|
|
168
|
+
function isTerminalIssueStateCategory(category) {
|
|
169
|
+
return category === "DONE" || category === "CANCELED";
|
|
170
|
+
}
|
|
167
171
|
//#endregion
|
|
168
|
-
export { effectiveIssueSort, getIssueComparator, getRepositoryIdentityForIssue, serializeIssue };
|
|
172
|
+
export { effectiveIssueSort, getIssueComparator, getRepositoryIdentityForIssue, isTerminalIssueStateCategory, serializeIssue };
|
|
169
173
|
|
|
170
174
|
//# sourceMappingURL=issue.utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"issue.utils.js","names":[],"sources":["../../../../git/src/utils/issue.utils.ts"],"sourcesContent":["import type {\n\tIssue,\n\tIssueRepositoryIdentityDescriptor,\n\tIssueShape,\n\tIssueSortField,\n\tIssueSorting,\n} from '../models/issue.js';\nimport { defaultIssueSort } from '../models/issue.js';\n\n/**\n * How each sort field is read off an {@link IssueShape}, for the reads that MERGE several provider queries and so\n * have to order the union themselves instead of letting the provider do it.\n *\n * Only the fields the shape actually carries appear. `priority`, `dueDate` and `resolved` are absent because\n * `IssueOrPullRequest`/`IssueShape` doesn't model them: a provider may well order by them server-side on a\n * single-query read, but a merged one cannot — which is exactly what {@link getIssueComparator} returning\n * `undefined` lets its caller refuse, instead of concatenating unordered runs and calling them sorted.\n */\nconst issueSortValues: Partial<Record<IssueSortField, (issue: IssueShape) => number | Date | string | undefined>> = {\n\tcreated: i => i.createdDate,\n\tupdated: i => i.updatedDate,\n\tclosed: i => i.closedDate,\n\tcomments: i => i.commentsCount,\n\treactions: i => i.thumbsUpCount,\n\ttitle: i => i.title,\n};\n\n/**\n * The order a read that ALWAYS orders is being made under: the caller's key, or the facade's default.\n *\n * The one place `?? defaultIssueSort` may be written. Several things downstream must agree on the answer — the\n * emitted provider qualifier, the fingerprint sealed into a cursor, the comparator that re-sorts a merged page and\n * the ceiling warning that names the order — and re-deriving the fallback at each is how they come to disagree,\n * which is not cosmetic: a cursor sealed with a key its query wasn't built with makes the fingerprint check refuse\n * valid resumptions.\n *\n * Note this is for a surface that CAN always order. A read whose provider may not express even the default resolves\n * through `resolveIssueSort` instead, which can answer \"leave the provider's own order\".\n */\nexport function effectiveIssueSort(sort: IssueSorting | undefined): IssueSorting {\n\treturn sort ?? defaultIssueSort;\n}\n\n/**\n * A comparator for one sort key over normalized issues, or `undefined` when the field isn't derivable from an\n * {@link IssueShape} — the signal that the key is only honorable on a SINGLE-origin read, where the provider\n * already ordered the page.\n *\n * `@gitkraken/provider-apis` carries a twin of this over its own `Issue` shape (`src/issueSort.ts`), which it uses\n * for the merges it performs itself. It is not importable — the SDK does not export it, and it takes a different\n * shape — so the two are separate implementations of one rule, and the rule below is the part that must not drift.\n *\n * Missing values sort LAST in both directions. That is deliberately not the same as negating the descending\n * comparator (which would float them to the front when ascending), and it is why they're partitioned before any\n * arithmetic rather than mapped to an infinite sentinel: two missing values have to compare equal, and\n * `-Infinity - -Infinity` is `NaN`, which makes the comparator inconsistent and the resulting order\n * implementation-defined.\n *\n * Note it orders whatever it is handed. Sorting a page that was already capped does not make it the top N.\n *\n * KNOWN DIVERGENCE, `title` only: strings are compared by code unit, so `'B' < 'a'`. A single-scope read is\n * ordered by the provider's own database instead — case-insensitive and accent-aware — so the same `title:asc`\n * yields \"Banana, apple, ábaco\" from a merged page and \"ábaco, apple, Banana\" from one repository. Deliberately\n * NOT fixed with `localeCompare`: the SDK's twin comparator (which performs the merges core doesn't, notably\n * GitLab's repo-ids aggregate) compares by code unit, so switching here would make two paths of the SAME\n * multi-repo read disagree — a worse divergence than the one it closes, and it would break the parity test in\n * `issueSortCapabilities.test.ts`. Closing this properly means changing the rule on BOTH sides at once; until\n * then it is a cosmetic ordering difference on one key, not wrong data.\n */\nexport function getIssueComparator(sort: IssueSorting): ((a: IssueShape, b: IssueShape) => number) | undefined {\n\t// The union's shape guarantees both halves, so this needs no validation — only the cast tsc can't infer.\n\tconst [field, direction] = sort.split(':') as [IssueSortField, 'asc' | 'desc'];\n\tconst getValue = issueSortValues[field];\n\tif (getValue == null) return undefined;\n\n\treturn (a, b) => {\n\t\tconst left = toComparable(getValue(a));\n\t\tconst right = toComparable(getValue(b));\n\t\tif (left == null || right == null) {\n\t\t\tif (left == null && right == null) return 0;\n\t\t\treturn left == null ? 1 : -1;\n\t\t}\n\n\t\tconst ordered = left < right ? -1 : left > right ? 1 : 0;\n\t\treturn direction === 'asc' ? ordered : -ordered;\n\t};\n}\n\nfunction toComparable(value: number | Date | string | undefined): number | string | undefined {\n\treturn value instanceof Date ? value.getTime() : value;\n}\n\nexport function getRepositoryIdentityForIssue(issue: IssueShape | Issue): IssueRepositoryIdentityDescriptor {\n\tif (issue.repository == null) throw new Error('Missing repository');\n\n\treturn {\n\t\tremote: {\n\t\t\turl: issue.repository.url,\n\t\t\tdomain: issue.provider.domain,\n\t\t},\n\t\tname: `${issue.repository.owner}/${issue.repository.repo}`,\n\t\tprovider: {\n\t\t\tid: issue.provider.id,\n\t\t\tdomain: issue.provider.domain,\n\t\t\trepoDomain: issue.repository.owner,\n\t\t\trepoName: issue.repository.repo,\n\t\t\trepoOwnerDomain: issue.repository.owner,\n\t\t},\n\t};\n}\n\n/**\n * Deliberately leaves `projection` out: this copy drops `repository.accessLevel`, so a tag would have field presence\n * report the viewer's access as fetched when the copy no longer has it.\n */\nexport function serializeIssue(value: IssueShape): IssueShape {\n\tconst serialized: IssueShape = {\n\t\ttype: value.type,\n\t\tprovider: {\n\t\t\tid: value.provider.id,\n\t\t\tname: value.provider.name,\n\t\t\tdomain: value.provider.domain,\n\t\t\ticon: value.provider.icon,\n\t\t},\n\t\tid: value.id,\n\t\tnodeId: value.nodeId,\n\t\tissueType: value.issueType,\n\t\ttitle: value.title,\n\t\turl: value.url,\n\t\tcreatedDate: value.createdDate,\n\t\tupdatedDate: value.updatedDate,\n\t\tclosedDate: value.closedDate,\n\t\tclosed: value.closed,\n\t\tstate: value.state,\n\t\tproviderState:\n\t\t\tvalue.providerState == null\n\t\t\t\t? undefined\n\t\t\t\t: {\n\t\t\t\t\t\tid: value.providerState.id,\n\t\t\t\t\t\tname: value.providerState.name,\n\t\t\t\t\t\tcolor: value.providerState.color,\n\t\t\t\t\t\tcategory: value.providerState.category,\n\t\t\t\t\t},\n\t\tauthor:\n\t\t\tvalue.author == null\n\t\t\t\t? undefined\n\t\t\t\t: {\n\t\t\t\t\t\tid: value.author.id,\n\t\t\t\t\t\tname: value.author.name,\n\t\t\t\t\t\tusername: value.author.username,\n\t\t\t\t\t\tavatarUrl: value.author.avatarUrl,\n\t\t\t\t\t\turl: value.author.url,\n\t\t\t\t\t},\n\t\trepository:\n\t\t\tvalue.repository == null\n\t\t\t\t? undefined\n\t\t\t\t: {\n\t\t\t\t\t\towner: value.repository.owner,\n\t\t\t\t\t\trepo: value.repository.repo,\n\t\t\t\t\t\turl: value.repository.url,\n\t\t\t\t\t},\n\t\tproject:\n\t\t\tvalue.project == null\n\t\t\t\t? undefined\n\t\t\t\t: {\n\t\t\t\t\t\tid: value.project.id,\n\t\t\t\t\t\tname: value.project.name,\n\t\t\t\t\t\tresourceId: value.project.resourceId,\n\t\t\t\t\t\tresourceName: value.project.resourceName,\n\t\t\t\t\t},\n\t\tassignees: value.assignees.map(assignee => ({\n\t\t\tid: assignee.id,\n\t\t\tname: assignee.name,\n\t\t\tusername: assignee.username,\n\t\t\tavatarUrl: assignee.avatarUrl,\n\t\t\turl: assignee.url,\n\t\t})),\n\t\tlabels:\n\t\t\tvalue.labels == null\n\t\t\t\t? undefined\n\t\t\t\t: value.labels.map(label => ({\n\t\t\t\t\t\tcolor: label.color,\n\t\t\t\t\t\tname: label.name,\n\t\t\t\t\t})),\n\t\tcommentsCount: value.commentsCount,\n\t\tthumbsUpCount: value.thumbsUpCount,\n\t\tbody: value.body,\n\t\tbodyFormat: value.bodyFormat,\n\t\titerations:\n\t\t\tvalue.iterations == null\n\t\t\t\t? undefined\n\t\t\t\t: value.iterations.map(iteration => ({\n\t\t\t\t\t\tid: iteration.id,\n\t\t\t\t\t\tname: iteration.name,\n\t\t\t\t\t\tisActive: iteration.isActive,\n\t\t\t\t\t\tstartDate: iteration.startDate,\n\t\t\t\t\t\tendDate: iteration.endDate,\n\t\t\t\t\t})),\n\t};\n\treturn serialized;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"issue.utils.js","names":[],"sources":["../../../../git/src/utils/issue.utils.ts"],"sourcesContent":["import type {\n\tIssue,\n\tIssueProviderState,\n\tIssueRepositoryIdentityDescriptor,\n\tIssueShape,\n\tIssueSortField,\n\tIssueSorting,\n} from '../models/issue.js';\nimport { defaultIssueSort } from '../models/issue.js';\n\n/**\n * How each sort field is read off an {@link IssueShape}, for the reads that MERGE several provider queries and so\n * have to order the union themselves instead of letting the provider do it.\n *\n * Only the fields the shape actually carries appear. `priority`, `dueDate` and `resolved` are absent because\n * `IssueOrPullRequest`/`IssueShape` doesn't model them: a provider may well order by them server-side on a\n * single-query read, but a merged one cannot — which is exactly what {@link getIssueComparator} returning\n * `undefined` lets its caller refuse, instead of concatenating unordered runs and calling them sorted.\n */\nconst issueSortValues: Partial<Record<IssueSortField, (issue: IssueShape) => number | Date | string | undefined>> = {\n\tcreated: i => i.createdDate,\n\tupdated: i => i.updatedDate,\n\tclosed: i => i.closedDate,\n\tcomments: i => i.commentsCount,\n\treactions: i => i.thumbsUpCount,\n\ttitle: i => i.title,\n};\n\n/**\n * The order a read that ALWAYS orders is being made under: the caller's key, or the facade's default.\n *\n * The one place `?? defaultIssueSort` may be written. Several things downstream must agree on the answer — the\n * emitted provider qualifier, the fingerprint sealed into a cursor, the comparator that re-sorts a merged page and\n * the ceiling warning that names the order — and re-deriving the fallback at each is how they come to disagree,\n * which is not cosmetic: a cursor sealed with a key its query wasn't built with makes the fingerprint check refuse\n * valid resumptions.\n *\n * Note this is for a surface that CAN always order. A read whose provider may not express even the default resolves\n * through `resolveIssueSort` instead, which can answer \"leave the provider's own order\".\n */\nexport function effectiveIssueSort(sort: IssueSorting | undefined): IssueSorting {\n\treturn sort ?? defaultIssueSort;\n}\n\n/**\n * A comparator for one sort key over normalized issues, or `undefined` when the field isn't derivable from an\n * {@link IssueShape} — the signal that the key is only honorable on a SINGLE-origin read, where the provider\n * already ordered the page.\n *\n * `@gitkraken/provider-apis` carries a twin of this over its own `Issue` shape (`src/issueSort.ts`), which it uses\n * for the merges it performs itself. It is not importable — the SDK does not export it, and it takes a different\n * shape — so the two are separate implementations of one rule, and the rule below is the part that must not drift.\n *\n * Missing values sort LAST in both directions. That is deliberately not the same as negating the descending\n * comparator (which would float them to the front when ascending), and it is why they're partitioned before any\n * arithmetic rather than mapped to an infinite sentinel: two missing values have to compare equal, and\n * `-Infinity - -Infinity` is `NaN`, which makes the comparator inconsistent and the resulting order\n * implementation-defined.\n *\n * Note it orders whatever it is handed. Sorting a page that was already capped does not make it the top N.\n *\n * KNOWN DIVERGENCE, `title` only: strings are compared by code unit, so `'B' < 'a'`. A single-scope read is\n * ordered by the provider's own database instead — case-insensitive and accent-aware — so the same `title:asc`\n * yields \"Banana, apple, ábaco\" from a merged page and \"ábaco, apple, Banana\" from one repository. Deliberately\n * NOT fixed with `localeCompare`: the SDK's twin comparator (which performs the merges core doesn't, notably\n * GitLab's repo-ids aggregate) compares by code unit, so switching here would make two paths of the SAME\n * multi-repo read disagree — a worse divergence than the one it closes, and it would break the parity test in\n * `issueSortCapabilities.test.ts`. Closing this properly means changing the rule on BOTH sides at once; until\n * then it is a cosmetic ordering difference on one key, not wrong data.\n */\nexport function getIssueComparator(sort: IssueSorting): ((a: IssueShape, b: IssueShape) => number) | undefined {\n\t// The union's shape guarantees both halves, so this needs no validation — only the cast tsc can't infer.\n\tconst [field, direction] = sort.split(':') as [IssueSortField, 'asc' | 'desc'];\n\tconst getValue = issueSortValues[field];\n\tif (getValue == null) return undefined;\n\n\treturn (a, b) => {\n\t\tconst left = toComparable(getValue(a));\n\t\tconst right = toComparable(getValue(b));\n\t\tif (left == null || right == null) {\n\t\t\tif (left == null && right == null) return 0;\n\t\t\treturn left == null ? 1 : -1;\n\t\t}\n\n\t\tconst ordered = left < right ? -1 : left > right ? 1 : 0;\n\t\treturn direction === 'asc' ? ordered : -ordered;\n\t};\n}\n\nfunction toComparable(value: number | Date | string | undefined): number | string | undefined {\n\treturn value instanceof Date ? value.getTime() : value;\n}\n\nexport function getRepositoryIdentityForIssue(issue: IssueShape | Issue): IssueRepositoryIdentityDescriptor {\n\tif (issue.repository == null) throw new Error('Missing repository');\n\n\treturn {\n\t\tremote: {\n\t\t\turl: issue.repository.url,\n\t\t\tdomain: issue.provider.domain,\n\t\t},\n\t\tname: `${issue.repository.owner}/${issue.repository.repo}`,\n\t\tprovider: {\n\t\t\tid: issue.provider.id,\n\t\t\tdomain: issue.provider.domain,\n\t\t\trepoDomain: issue.repository.owner,\n\t\t\trepoName: issue.repository.repo,\n\t\t\trepoOwnerDomain: issue.repository.owner,\n\t\t},\n\t};\n}\n\n/**\n * Deliberately leaves `projection` out: this copy drops `repository.accessLevel`, so a tag would have field presence\n * report the viewer's access as fetched when the copy no longer has it.\n */\nexport function serializeIssue(value: IssueShape): IssueShape {\n\tconst serialized: IssueShape = {\n\t\ttype: value.type,\n\t\tprovider: {\n\t\t\tid: value.provider.id,\n\t\t\tname: value.provider.name,\n\t\t\tdomain: value.provider.domain,\n\t\t\ticon: value.provider.icon,\n\t\t},\n\t\tid: value.id,\n\t\tnodeId: value.nodeId,\n\t\tissueType: value.issueType,\n\t\ttitle: value.title,\n\t\turl: value.url,\n\t\tcreatedDate: value.createdDate,\n\t\tupdatedDate: value.updatedDate,\n\t\tclosedDate: value.closedDate,\n\t\tclosed: value.closed,\n\t\tstate: value.state,\n\t\tproviderState:\n\t\t\tvalue.providerState == null\n\t\t\t\t? undefined\n\t\t\t\t: {\n\t\t\t\t\t\tid: value.providerState.id,\n\t\t\t\t\t\tname: value.providerState.name,\n\t\t\t\t\t\tcolor: value.providerState.color,\n\t\t\t\t\t\tcategory: value.providerState.category,\n\t\t\t\t\t},\n\t\tauthor:\n\t\t\tvalue.author == null\n\t\t\t\t? undefined\n\t\t\t\t: {\n\t\t\t\t\t\tid: value.author.id,\n\t\t\t\t\t\tname: value.author.name,\n\t\t\t\t\t\tusername: value.author.username,\n\t\t\t\t\t\tavatarUrl: value.author.avatarUrl,\n\t\t\t\t\t\turl: value.author.url,\n\t\t\t\t\t},\n\t\trepository:\n\t\t\tvalue.repository == null\n\t\t\t\t? undefined\n\t\t\t\t: {\n\t\t\t\t\t\towner: value.repository.owner,\n\t\t\t\t\t\trepo: value.repository.repo,\n\t\t\t\t\t\turl: value.repository.url,\n\t\t\t\t\t},\n\t\tproject:\n\t\t\tvalue.project == null\n\t\t\t\t? undefined\n\t\t\t\t: {\n\t\t\t\t\t\tid: value.project.id,\n\t\t\t\t\t\tname: value.project.name,\n\t\t\t\t\t\tresourceId: value.project.resourceId,\n\t\t\t\t\t\tresourceName: value.project.resourceName,\n\t\t\t\t\t},\n\t\tassignees: value.assignees.map(assignee => ({\n\t\t\tid: assignee.id,\n\t\t\tname: assignee.name,\n\t\t\tusername: assignee.username,\n\t\t\tavatarUrl: assignee.avatarUrl,\n\t\t\turl: assignee.url,\n\t\t})),\n\t\tlabels:\n\t\t\tvalue.labels == null\n\t\t\t\t? undefined\n\t\t\t\t: value.labels.map(label => ({\n\t\t\t\t\t\tcolor: label.color,\n\t\t\t\t\t\tname: label.name,\n\t\t\t\t\t})),\n\t\tcommentsCount: value.commentsCount,\n\t\tthumbsUpCount: value.thumbsUpCount,\n\t\tbody: value.body,\n\t\tbodyFormat: value.bodyFormat,\n\t\titerations:\n\t\t\tvalue.iterations == null\n\t\t\t\t? undefined\n\t\t\t\t: value.iterations.map(iteration => ({\n\t\t\t\t\t\tid: iteration.id,\n\t\t\t\t\t\tname: iteration.name,\n\t\t\t\t\t\tisActive: iteration.isActive,\n\t\t\t\t\t\tstartDate: iteration.startDate,\n\t\t\t\t\t\tendDate: iteration.endDate,\n\t\t\t\t\t})),\n\t};\n\treturn serialized;\n}\n\n/** Whether a provider's workflow category ends the issue: done or abandoned (see {@link IssueProviderState.category}). */\nexport function isTerminalIssueStateCategory(category: IssueProviderState['category']): boolean {\n\treturn category === 'DONE' || category === 'CANCELED';\n}\n"],"mappings":"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"}
|
|
@@ -13,9 +13,9 @@ import { isAzureProviderId } from "../providers/providerErrors.js";
|
|
|
13
13
|
import { throwIfCallerContractError, toCollectionFailureError, toCollectionScopeFailure } from "../collectionMetadata.js";
|
|
14
14
|
import { toTokenWithInfo } from "../authentication/models.js";
|
|
15
15
|
import "../providerFilters.js";
|
|
16
|
-
import { mergeCollectionMetadata, throwIfAllSettledFailed } from "../providers/utils/providerPaging.js";
|
|
17
16
|
import { areDomainsOnSameHost } from "../utils/domain.utils.js";
|
|
18
17
|
import { getSelfManagedBaseUrl, isGitSelfManagedHostIntegrationId } from "../utils/integration.utils.js";
|
|
18
|
+
import { mergeCollectionMetadata, throwIfAllSettledFailed } from "../providers/utils/providerPaging.js";
|
|
19
19
|
import { toIssueShape, toProviderIssueStates, toProviderPullRequestStates } from "../providers/models.js";
|
|
20
20
|
import { IntegrationBase, isReadSessionFailure } from "./integration.js";
|
|
21
21
|
//#region ../plus/integrations/src/models/gitHostIntegration.ts
|
|
@@ -571,6 +571,8 @@ var GitHostIntegration = class extends IntegrationBase {
|
|
|
571
571
|
}
|
|
572
572
|
const { projectInput: _projectInput, results } = outcome.value;
|
|
573
573
|
data.push(...results.values);
|
|
574
|
+
if (results.paging?.truncated) truncated = true;
|
|
575
|
+
metadata = mergeCollectionMetadata(metadata, results.metadata);
|
|
574
576
|
if (results.paging?.more) {
|
|
575
577
|
hasMore = true;
|
|
576
578
|
cursor.cursors.push({
|