@gitkraken/core-gitlens 0.16.0 → 0.16.2
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 +22 -1
- package/dist/git/cache.js +2 -2
- package/dist/git/cache.js.map +1 -1
- package/dist/git/run.types.d.ts +3 -0
- package/dist/git/watching/classifyChange.js +3 -0
- package/dist/git/watching/classifyChange.js.map +1 -1
- package/dist/git/watching/watchSession.d.ts +2 -0
- package/dist/git/watching/watchSession.js +9 -1
- package/dist/git/watching/watchSession.js.map +1 -1
- package/dist/git-cli/cliGitProvider.d.ts +1 -1
- package/dist/git-cli/cliGitProvider.js +7 -4
- package/dist/git-cli/cliGitProvider.js.map +1 -1
- package/dist/git-cli/exec/commandClassifier.d.ts +18 -3
- package/dist/git-cli/exec/commandClassifier.js +562 -16
- package/dist/git-cli/exec/commandClassifier.js.map +1 -1
- package/dist/git-cli/exec/exec.d.ts +2 -2
- package/dist/git-cli/exec/git.d.ts +31 -4
- package/dist/git-cli/exec/git.js +105 -43
- package/dist/git-cli/exec/git.js.map +1 -1
- package/dist/git-cli/exec/headState.d.ts +32 -0
- package/dist/git-cli/exec/headState.js +78 -0
- package/dist/git-cli/exec/headState.js.map +1 -0
- package/dist/git-cli/providers/branches.js +14 -4
- package/dist/git-cli/providers/branches.js.map +1 -1
- package/dist/git-cli/providers/operations.d.ts +6 -7
- package/dist/git-cli/providers/operations.js +46 -64
- package/dist/git-cli/providers/operations.js.map +1 -1
- package/dist/git-cli/providers/refs.d.ts +4 -1
- package/dist/git-cli/providers/refs.js +13 -9
- package/dist/git-cli/providers/refs.js.map +1 -1
- package/dist/plus/integrations/integrationService.d.ts +1 -0
- package/dist/plus/integrations/integrationService.js +18 -5
- package/dist/plus/integrations/integrationService.js.map +1 -1
- package/dist/plus/integrations/providers/apiClients.d.ts +2 -0
- package/dist/plus/integrations/providers/apiClients.js +12 -3
- package/dist/plus/integrations/providers/apiClients.js.map +1 -1
- package/dist/plus/integrations/providers/azure/azure.d.ts +13 -11
- package/dist/plus/integrations/providers/azure/azure.js +128 -47
- package/dist/plus/integrations/providers/azure/azure.js.map +1 -1
- package/dist/plus/integrations/providers/azure/models.d.ts +4 -10
- package/dist/plus/integrations/providers/azure/models.js +25 -9
- package/dist/plus/integrations/providers/azure/models.js.map +1 -1
- package/dist/plus/integrations/providers/azure/workItemDescriptions.d.ts +10 -0
- package/dist/plus/integrations/providers/azure/workItemDescriptions.js +48 -0
- package/dist/plus/integrations/providers/azure/workItemDescriptions.js.map +1 -0
- package/dist/plus/integrations/providers/azure/workItemStateCategories.d.ts +20 -19
- package/dist/plus/integrations/providers/azure/workItemStateCategories.js +65 -40
- package/dist/plus/integrations/providers/azure/workItemStateCategories.js.map +1 -1
- package/dist/plus/integrations/providers/issueSorts.d.ts +0 -1
- package/dist/plus/integrations/providers/providerApiClient.d.ts +9 -0
- package/dist/plus/integrations/providers/providerApiClient.js +66 -0
- package/dist/plus/integrations/providers/providerApiClient.js.map +1 -0
- package/dist/plus/integrations/providers/providersApi.d.ts +10 -9
- package/dist/plus/integrations/providers/providersApi.js +163 -145
- package/dist/plus/integrations/providers/providersApi.js.map +1 -1
- package/dist/plus/integrations/reads/drains.d.ts +0 -1
- package/dist/utils/env/node/exec.d.ts +38 -1
- package/dist/utils/env/node/exec.js +14 -6
- package/dist/utils/env/node/exec.js.map +1 -1
- package/docs/integrations.md +30 -13
- package/package.json +2 -2
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Disposable } from "../../../utils/disposable.js";
|
|
2
2
|
import { GitHubApi } from "../../git-github/api/github.js";
|
|
3
3
|
import { AzureWorkItemStatesCache } from "./azure/workItemStateCategories.js";
|
|
4
|
+
import { AzureWorkItemDescriptionsCache } from "./azure/workItemDescriptions.js";
|
|
4
5
|
import { AzureDevOpsApi } from "./azure/azure.js";
|
|
5
6
|
import { BitbucketApi } from "./bitbucket/bitbucket.js";
|
|
6
7
|
import "./github/github.js";
|
|
@@ -15,6 +16,7 @@ import { IntegrationServiceContext } from "../context.js";
|
|
|
15
16
|
*/
|
|
16
17
|
export interface ApiClients {
|
|
17
18
|
readonly azureWorkItemStates: AzureWorkItemStatesCache;
|
|
19
|
+
readonly azureWorkItemDescriptions: AzureWorkItemDescriptionsCache;
|
|
18
20
|
readonly github: Promise<GitHubApi | undefined>;
|
|
19
21
|
readonly gitlab: Promise<GitLabApi | undefined>;
|
|
20
22
|
readonly bitbucket: Promise<BitbucketApi | undefined>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getScopedLogger } from "../../../utils/logger.scoped.js";
|
|
2
|
+
import { AzureWorkItemDescriptionsCache } from "./azure/workItemDescriptions.js";
|
|
2
3
|
import { AzureWorkItemStatesCache } from "./azure/workItemStateCategories.js";
|
|
3
4
|
//#region ../plus/integrations/src/providers/apiClients.ts
|
|
4
5
|
/**
|
|
@@ -8,9 +9,16 @@ import { AzureWorkItemStatesCache } from "./azure/workItemStateCategories.js";
|
|
|
8
9
|
*/
|
|
9
10
|
function createApiClients(ctx, disposables) {
|
|
10
11
|
const azureWorkItemStates = new AzureWorkItemStatesCache();
|
|
12
|
+
const azureWorkItemDescriptions = new AzureWorkItemDescriptionsCache();
|
|
11
13
|
disposables.push(ctx.config.onDidChange((e) => {
|
|
12
|
-
if (e.httpProxy)
|
|
13
|
-
|
|
14
|
+
if (e.httpProxy) {
|
|
15
|
+
azureWorkItemStates.clear();
|
|
16
|
+
azureWorkItemDescriptions.clear();
|
|
17
|
+
}
|
|
18
|
+
}), { dispose: () => {
|
|
19
|
+
azureWorkItemStates.clear();
|
|
20
|
+
azureWorkItemDescriptions.clear();
|
|
21
|
+
} });
|
|
14
22
|
let github;
|
|
15
23
|
let gitlab;
|
|
16
24
|
let bitbucket;
|
|
@@ -28,6 +36,7 @@ function createApiClients(ctx, disposables) {
|
|
|
28
36
|
};
|
|
29
37
|
return {
|
|
30
38
|
azureWorkItemStates,
|
|
39
|
+
azureWorkItemDescriptions,
|
|
31
40
|
get github() {
|
|
32
41
|
return github ??= build(async () => (await import(
|
|
33
42
|
/* webpackChunkName: "integrations" */
|
|
@@ -50,7 +59,7 @@ function createApiClients(ctx, disposables) {
|
|
|
50
59
|
return azure ??= build(async () => (await import(
|
|
51
60
|
/* webpackChunkName: "integrations" */
|
|
52
61
|
"./azure/azure.js"
|
|
53
|
-
)).createAzureDevOpsApi(ctx, azureWorkItemStates));
|
|
62
|
+
)).createAzureDevOpsApi(ctx, azureWorkItemStates, azureWorkItemDescriptions));
|
|
54
63
|
}
|
|
55
64
|
};
|
|
56
65
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apiClients.js","names":[],"sources":["../../../../../plus/integrations/src/providers/apiClients.ts"],"sourcesContent":["import type { Disposable } from '@gitlens/utils/disposable.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport type { IntegrationServiceContext } from '../context.js';\nimport type { AzureDevOpsApi } from './azure/azure.js';\nimport { AzureWorkItemStatesCache } from './azure/workItemStateCategories.js';\nimport type { BitbucketApi } from './bitbucket/bitbucket.js';\nimport type { GitHubApi } from './github/github.js';\nimport type { GitLabApi } from './gitlab/gitlab.js';\n\n/**\n * The per-provider API clients, owned and built by the package. `GitLabApi`/`BitbucketApi`/`AzureDevOpsApi`\n * live in the package; `GitHubApi` comes from `@gitlens/git-github` (shared with the host's GitHub git\n * provider, which reads the manager's memoized instance via `manager.github`). `undefined` is tolerated for\n * offline/limited runtimes.\n */\nexport interface ApiClients {\n\treadonly azureWorkItemStates: AzureWorkItemStatesCache;\n\treadonly github: Promise<GitHubApi | undefined>;\n\treadonly gitlab: Promise<GitLabApi | undefined>;\n\treadonly bitbucket: Promise<BitbucketApi | undefined>;\n\treadonly azure: Promise<AzureDevOpsApi | undefined>;\n}\n\n/**\n * Lazily constructs + memoizes the API clients from the runtime context, pushing each to `disposables` for\n * teardown. Mirrors the lazy-chunked construction the host's `Container` did before the package took\n * ownership (the host used to build these and inject them back through the context — a pure round-trip).\n */\nexport function createApiClients(ctx: IntegrationServiceContext, disposables: Disposable[]): ApiClients {\n\tconst azureWorkItemStates = new AzureWorkItemStatesCache();\n\tdisposables.push(\n\t\tctx.config.onDidChange(e => {\n\t\t\tif (e.httpProxy) {\n\t\t\t\tazureWorkItemStates.clear();\n\t\t\t}\n\t\t}),\n\t\t{
|
|
1
|
+
{"version":3,"file":"apiClients.js","names":[],"sources":["../../../../../plus/integrations/src/providers/apiClients.ts"],"sourcesContent":["import type { Disposable } from '@gitlens/utils/disposable.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport type { IntegrationServiceContext } from '../context.js';\nimport type { AzureDevOpsApi } from './azure/azure.js';\nimport { AzureWorkItemDescriptionsCache } from './azure/workItemDescriptions.js';\nimport { AzureWorkItemStatesCache } from './azure/workItemStateCategories.js';\nimport type { BitbucketApi } from './bitbucket/bitbucket.js';\nimport type { GitHubApi } from './github/github.js';\nimport type { GitLabApi } from './gitlab/gitlab.js';\n\n/**\n * The per-provider API clients, owned and built by the package. `GitLabApi`/`BitbucketApi`/`AzureDevOpsApi`\n * live in the package; `GitHubApi` comes from `@gitlens/git-github` (shared with the host's GitHub git\n * provider, which reads the manager's memoized instance via `manager.github`). `undefined` is tolerated for\n * offline/limited runtimes.\n */\nexport interface ApiClients {\n\treadonly azureWorkItemStates: AzureWorkItemStatesCache;\n\treadonly azureWorkItemDescriptions: AzureWorkItemDescriptionsCache;\n\treadonly github: Promise<GitHubApi | undefined>;\n\treadonly gitlab: Promise<GitLabApi | undefined>;\n\treadonly bitbucket: Promise<BitbucketApi | undefined>;\n\treadonly azure: Promise<AzureDevOpsApi | undefined>;\n}\n\n/**\n * Lazily constructs + memoizes the API clients from the runtime context, pushing each to `disposables` for\n * teardown. Mirrors the lazy-chunked construction the host's `Container` did before the package took\n * ownership (the host used to build these and inject them back through the context — a pure round-trip).\n */\nexport function createApiClients(ctx: IntegrationServiceContext, disposables: Disposable[]): ApiClients {\n\tconst azureWorkItemStates = new AzureWorkItemStatesCache();\n\tconst azureWorkItemDescriptions = new AzureWorkItemDescriptionsCache();\n\tdisposables.push(\n\t\tctx.config.onDidChange(e => {\n\t\t\tif (e.httpProxy) {\n\t\t\t\tazureWorkItemStates.clear();\n\t\t\t\tazureWorkItemDescriptions.clear();\n\t\t\t}\n\t\t}),\n\t\t{\n\t\t\tdispose: () => {\n\t\t\t\tazureWorkItemStates.clear();\n\t\t\t\tazureWorkItemDescriptions.clear();\n\t\t\t},\n\t\t},\n\t);\n\tlet github: Promise<GitHubApi | undefined> | undefined;\n\tlet gitlab: Promise<GitLabApi | undefined> | undefined;\n\tlet bitbucket: Promise<BitbucketApi | undefined> | undefined;\n\tlet azure: Promise<AzureDevOpsApi | undefined> | undefined;\n\n\tconst build = async <T extends Disposable>(load: () => Promise<T>): Promise<T | undefined> => {\n\t\tconst scope = getScopedLogger();\n\t\ttry {\n\t\t\tconst api = await load();\n\t\t\tdisposables.push(api);\n\t\t\treturn api;\n\t\t} catch (ex) {\n\t\t\tscope?.error(ex, 'Failed to construct integration API client');\n\t\t\treturn undefined;\n\t\t}\n\t};\n\n\treturn {\n\t\tazureWorkItemStates: azureWorkItemStates,\n\t\tazureWorkItemDescriptions: azureWorkItemDescriptions,\n\t\tget github() {\n\t\t\treturn (github ??= build(async () =>\n\t\t\t\t(await import(/* webpackChunkName: \"integrations\" */ './github/github.js')).createGitHubApi(ctx),\n\t\t\t));\n\t\t},\n\t\tget gitlab() {\n\t\t\treturn (gitlab ??= build(async () =>\n\t\t\t\t(await import(/* webpackChunkName: \"integrations\" */ './gitlab/gitlab.js')).createGitLabApi(ctx),\n\t\t\t));\n\t\t},\n\t\tget bitbucket() {\n\t\t\treturn (bitbucket ??= build(async () =>\n\t\t\t\t(await import(/* webpackChunkName: \"integrations\" */ './bitbucket/bitbucket.js')).createBitbucketApi(\n\t\t\t\t\tctx,\n\t\t\t\t),\n\t\t\t));\n\t\t},\n\t\tget azure() {\n\t\t\treturn (azure ??= build(async () =>\n\t\t\t\t(await import(/* webpackChunkName: \"integrations\" */ './azure/azure.js')).createAzureDevOpsApi(\n\t\t\t\t\tctx,\n\t\t\t\t\tazureWorkItemStates,\n\t\t\t\t\tazureWorkItemDescriptions,\n\t\t\t\t),\n\t\t\t));\n\t\t},\n\t};\n}\n"],"mappings":";;;;;;;;;AA8BA,SAAgB,iBAAiB,KAAgC,aAAuC;CACvG,MAAM,sBAAsB,IAAI,yBAAyB;CACzD,MAAM,4BAA4B,IAAI,+BAA+B;CACrE,YAAY,KACX,IAAI,OAAO,aAAY,MAAK;EAC3B,IAAI,EAAE,WAAW;GAChB,oBAAoB,MAAM;GAC1B,0BAA0B,MAAM;EACjC;CACD,CAAC,GACD,EACC,eAAe;EACd,oBAAoB,MAAM;EAC1B,0BAA0B,MAAM;CACjC,EACD,CACD;CACA,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CAEJ,MAAM,QAAQ,OAA6B,SAAmD;EAC7F,MAAM,QAAQ,gBAAgB;EAC9B,IAAI;GACH,MAAM,MAAM,MAAM,KAAK;GACvB,YAAY,KAAK,GAAG;GACpB,OAAO;EACR,SAAS,IAAI;GACZ,OAAO,MAAM,IAAI,4CAA4C;GAC7D;EACD;CACD;CAEA,OAAO;EACe;EACM;EAC3B,IAAI,SAAS;GACZ,OAAQ,WAAW,MAAM,aACvB,MAAM;;IAA8C;EAAqB,CAAE,gBAAgB,GAAG,CAChG;EACD;EACA,IAAI,SAAS;GACZ,OAAQ,WAAW,MAAM,aACvB,MAAM;;IAA8C;EAAqB,CAAE,gBAAgB,GAAG,CAChG;EACD;EACA,IAAI,YAAY;GACf,OAAQ,cAAc,MAAM,aAC1B,MAAM;;IAA8C;EAA2B,CAAE,mBACjF,GACD,CACD;EACD;EACA,IAAI,QAAQ;GACX,OAAQ,UAAU,MAAM,aACtB,MAAM;;IAA8C;EAAmB,CAAE,qBACzE,KACA,qBACA,yBACD,CACD;EACD;CACD;AACD"}
|
|
@@ -9,6 +9,7 @@ import { RepositoryMetadata } from "../../../../git/models/repositoryMetadata.js
|
|
|
9
9
|
import { TokenWithInfo } from "../../authentication/models.js";
|
|
10
10
|
import { AzureProjectDescriptor, AzureWorkItemStateCategory } from "./models.js";
|
|
11
11
|
import { AzureWorkItemStatesCache } from "./workItemStateCategories.js";
|
|
12
|
+
import { AzureWorkItemDescriptionsCache } from "./workItemDescriptions.js";
|
|
12
13
|
import { ProviderIssueSearchPage } from "../../models/issueReads.js";
|
|
13
14
|
import { ProviderApiConfig } from "../apiConfig.js";
|
|
14
15
|
import { IntegrationServiceContext } from "../../context.js";
|
|
@@ -21,9 +22,12 @@ type WorkItemSearchOptions = {
|
|
|
21
22
|
};
|
|
22
23
|
export declare class AzureDevOpsApi implements Disposable {
|
|
23
24
|
private readonly config;
|
|
25
|
+
private readonly restApi;
|
|
24
26
|
private readonly _disposable;
|
|
25
27
|
private readonly _workItemStates;
|
|
26
28
|
private readonly ownsWorkItemStates;
|
|
29
|
+
private readonly _workItemDescriptions;
|
|
30
|
+
private readonly ownsWorkItemDescriptions;
|
|
27
31
|
private readonly _forkRepositoryUrls;
|
|
28
32
|
/**
|
|
29
33
|
* The ordered ids each filtered work-item search's first page queried, paged through by its continuations. Kept
|
|
@@ -31,7 +35,7 @@ export declare class AzureDevOpsApi implements Disposable {
|
|
|
31
35
|
* the capacity leaves room for repeated first pages before an idle pagination's snapshot is the one evicted.
|
|
32
36
|
*/
|
|
33
37
|
private readonly _workItemSearches;
|
|
34
|
-
constructor(config: ProviderApiConfig, workItemStates?: AzureWorkItemStatesCache);
|
|
38
|
+
constructor(config: ProviderApiConfig, workItemStates?: AzureWorkItemStatesCache, workItemDescriptions?: AzureWorkItemDescriptionsCache);
|
|
35
39
|
dispose(): void;
|
|
36
40
|
private resetCaches;
|
|
37
41
|
getPullRequestForBranch(provider: Provider, token: TokenWithInfo, owner: string, repo: string, branch: string, options: {
|
|
@@ -76,6 +80,7 @@ export declare class AzureDevOpsApi implements Disposable {
|
|
|
76
80
|
getWorkItemStateCategory(issueType: string, state: string, provider: Provider, token: TokenWithInfo, owner: string, projectName: string, options: {
|
|
77
81
|
baseUrl: string;
|
|
78
82
|
}, cancellation?: AbortSignal): Promise<AzureWorkItemStateCategory | undefined>;
|
|
83
|
+
private getWorkItemTypeStates;
|
|
79
84
|
getRepositoryMetadata(provider: Provider, token: TokenWithInfo, owner: string, repo: string, options: {
|
|
80
85
|
baseUrl: string;
|
|
81
86
|
}, cancellation?: AbortSignal): Promise<RepositoryMetadata | undefined>;
|
|
@@ -118,19 +123,11 @@ export declare class AzureDevOpsApi implements Disposable {
|
|
|
118
123
|
/**
|
|
119
124
|
* The ids a collection-level WIQL query matches, in its order.
|
|
120
125
|
*
|
|
121
|
-
* `
|
|
122
|
-
* answers; `timePrecision=true` is what lets the criteria's dates compare as instants — see `toWiqlDate`.
|
|
126
|
+
* `timePrecision=true` lets the criteria's dates compare as instants, including on legacy servers.
|
|
123
127
|
*/
|
|
124
128
|
private queryWorkItemIds;
|
|
125
129
|
private getRepository;
|
|
126
130
|
private toPullRequest;
|
|
127
|
-
/**
|
|
128
|
-
* The organization's rich text fields a work item's description may come from, for a work item none of the
|
|
129
|
-
* built-in description fields describes. Best-effort: a failed read leaves the description to those fields rather
|
|
130
|
-
* than failing the work item, so it is `undefined` on any failure but a cancellation. Logs to the caller's `scope`,
|
|
131
|
-
* captured before its first `await`: a scope read here, after the caller's reads, can be stale in a browser.
|
|
132
|
-
*/
|
|
133
|
-
private getWorkItemHtmlFields;
|
|
134
131
|
/**
|
|
135
132
|
* Resolves the web and HTTPS clone URLs of the fork a cross-repository pull request comes from. Every other
|
|
136
133
|
* repository URL the model reports is rebuilt from the pull request payload; only a fork reference lacks the
|
|
@@ -142,10 +139,15 @@ export declare class AzureDevOpsApi implements Disposable {
|
|
|
142
139
|
*/
|
|
143
140
|
private getForkRepositoryUrls;
|
|
144
141
|
private fetchForkRepositoryUrls;
|
|
142
|
+
private getWorkItem;
|
|
143
|
+
private requireWorkItemProject;
|
|
144
|
+
private getWorkItemHtmlFields;
|
|
145
|
+
private getRestResource;
|
|
146
|
+
private requireRestResource;
|
|
145
147
|
private request;
|
|
146
148
|
private handleRequestError;
|
|
147
149
|
}
|
|
148
150
|
/** Wires an {@link AzureDevOpsApi} from the full runtime context, mapping `ctx` down to the narrow config. */
|
|
149
|
-
export declare function createAzureDevOpsApi(ctx: IntegrationServiceContext, workItemStates?: AzureWorkItemStatesCache): AzureDevOpsApi;
|
|
151
|
+
export declare function createAzureDevOpsApi(ctx: IntegrationServiceContext, workItemStates?: AzureWorkItemStatesCache, workItemDescriptions?: AzureWorkItemDescriptionsCache): AzureDevOpsApi;
|
|
150
152
|
//#endregion
|
|
151
153
|
//# sourceMappingURL=azure.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CancellationError, isCancellationError } from "../../../../utils/cancellation.js";
|
|
1
|
+
import { CancellationError, isCancellationError, raceWithSignal } from "../../../../utils/cancellation.js";
|
|
2
2
|
import { Logger as _logger } from "../../../../utils/logger.js";
|
|
3
3
|
import { getScopedLogger } from "../../../../utils/logger.scoped.js";
|
|
4
4
|
import { mapBounded } from "../../../../utils/promise.js";
|
|
@@ -11,14 +11,16 @@ import { base64 } from "../../../../utils/base64.js";
|
|
|
11
11
|
import { sha256, uuid } from "../../../../utils/crypto.js";
|
|
12
12
|
import { effectiveIssueSort } from "../../../../git/utils/issue.utils.js";
|
|
13
13
|
import { ProviderFetchError, isRateLimitResponse, toRateLimitError } from "../../errors.js";
|
|
14
|
+
import { throwProviderError } from "../providerErrors.js";
|
|
14
15
|
import { decodePathSegment } from "../../utils/domain.utils.js";
|
|
15
16
|
import { azureWorkItemSearchResultLimit, parseAzureWorkItemSearchCursor, toAzureSearchPageSize, toAzureWorkItemSearchCursorKey, toAzureWorkItemSearchQueries, toAzureWorkItemSearchWiql } from "./search.js";
|
|
16
17
|
import { azurePullRequestStatusToState, azureWorkItemsStateCategoryToState, encodeAzurePathSegment, fromAzurePullRequest, fromAzureWorkItem, getAzurePullRequestWebUrl, isClosedAzurePullRequestStatus, normalizeAzureBranchName, parseAzureWorkItemDate, sanitizeAzureRepositoryUrl } from "./models.js";
|
|
17
|
-
import {
|
|
18
|
+
import { AzureWorkItemDescriptionsCache } from "./workItemDescriptions.js";
|
|
19
|
+
import { AzureWorkItemStatesCache, getAzureWorkItemTypeStatesPath, getAzureWorkItemTypesUrl, requireAzureWorkItemStateCategories, resolveAzureWorkItemStateCategory } from "./workItemStateCategories.js";
|
|
18
20
|
import { baseProviderApiConfig } from "../apiConfig.js";
|
|
21
|
+
import { createProviderApiRequest, createProviderApis } from "../providerApiClient.js";
|
|
19
22
|
import { queryAzureWorkItemSearch } from "./workItemSearch.js";
|
|
20
23
|
import * as l10n from "@vscode/l10n";
|
|
21
|
-
import { needsAzureWorkItemHtmlFields } from "@gitkraken/provider-apis";
|
|
22
24
|
//#region ../plus/integrations/src/providers/azure/azure.ts
|
|
23
25
|
const forkRepositoryUrlCacheTtl = 3e5;
|
|
24
26
|
const workItemMetadataConcurrency = 6;
|
|
@@ -40,9 +42,12 @@ function parseAzureRepositoryDescriptor(repo) {
|
|
|
40
42
|
}
|
|
41
43
|
var AzureDevOpsApi = class {
|
|
42
44
|
config;
|
|
45
|
+
restApi;
|
|
43
46
|
_disposable;
|
|
44
47
|
_workItemStates;
|
|
45
48
|
ownsWorkItemStates;
|
|
49
|
+
_workItemDescriptions;
|
|
50
|
+
ownsWorkItemDescriptions;
|
|
46
51
|
_forkRepositoryUrls = new PromiseCache({
|
|
47
52
|
capacity: 100,
|
|
48
53
|
createTTL: forkRepositoryUrlCacheTtl
|
|
@@ -57,17 +62,22 @@ var AzureDevOpsApi = class {
|
|
|
57
62
|
accessTTL: workItemSearchSnapshotTtl,
|
|
58
63
|
createTTL: workItemSearchSnapshotMaxTtl
|
|
59
64
|
});
|
|
60
|
-
constructor(config, workItemStates) {
|
|
65
|
+
constructor(config, workItemStates, workItemDescriptions) {
|
|
61
66
|
this.config = config;
|
|
67
|
+
this.restApi = createProviderApis({ request: createProviderApiRequest((input, init) => config.fetch(input, init)) }).azureDevOps;
|
|
62
68
|
this._workItemStates = workItemStates ?? new AzureWorkItemStatesCache();
|
|
63
69
|
this.ownsWorkItemStates = workItemStates == null;
|
|
70
|
+
this._workItemDescriptions = workItemDescriptions ?? new AzureWorkItemDescriptionsCache();
|
|
71
|
+
this.ownsWorkItemDescriptions = workItemDescriptions == null;
|
|
64
72
|
this._disposable = config.onConfigChanged?.(() => this.resetCaches());
|
|
65
73
|
}
|
|
66
74
|
dispose() {
|
|
67
75
|
this._disposable?.dispose();
|
|
68
76
|
}
|
|
69
77
|
resetCaches() {
|
|
78
|
+
this.restApi.updateConfig({});
|
|
70
79
|
if (this.ownsWorkItemStates) this._workItemStates.clear();
|
|
80
|
+
if (this.ownsWorkItemDescriptions) this._workItemDescriptions.clear();
|
|
71
81
|
this._forkRepositoryUrls.clear();
|
|
72
82
|
this._workItemSearches.clear();
|
|
73
83
|
}
|
|
@@ -92,8 +102,11 @@ var AzureDevOpsApi = class {
|
|
|
92
102
|
async getPullRequestForCommit(provider, token, owner, repo, rev, baseUrl, _options, cancellation) {
|
|
93
103
|
const scope = getScopedLogger();
|
|
94
104
|
const { projectName, repoName } = parseAzureRepositoryDescriptor(repo);
|
|
105
|
+
const resource = await this.requireRestResource(provider, token, owner, baseUrl, "pullRequestQuery", "4.1", cancellation);
|
|
95
106
|
try {
|
|
96
|
-
const
|
|
107
|
+
const encodedProject = encodeAzurePathSegment(projectName);
|
|
108
|
+
const encodedRepo = encodeAzurePathSegment(repoName);
|
|
109
|
+
const pr = (await this.request(provider, token, baseUrl, `${encodeAzurePathSegment(owner)}/${encodedProject}/_apis/git/repositories/${encodedRepo}/pullrequestquery?api-version=${resource.apiVersion}`, {
|
|
97
110
|
method: "POST",
|
|
98
111
|
body: JSON.stringify({ queries: [{
|
|
99
112
|
items: [rev],
|
|
@@ -125,9 +138,10 @@ var AzureDevOpsApi = class {
|
|
|
125
138
|
const scope = getScopedLogger();
|
|
126
139
|
const { projectName, repoName } = parseAzureRepositoryDescriptor(repo);
|
|
127
140
|
if (options?.type === void 0 || options?.type === "issue") {
|
|
141
|
+
const resource = await this.requireRestResource(provider, token, owner, options.baseUrl, "workItems", "6.0");
|
|
128
142
|
let issueResult;
|
|
129
143
|
try {
|
|
130
|
-
issueResult = await this.
|
|
144
|
+
issueResult = await this.getWorkItem(provider, token, owner, projectName, id, options.baseUrl, resource, scope);
|
|
131
145
|
} catch (ex) {
|
|
132
146
|
if (ex instanceof AuthenticationError) throw ex;
|
|
133
147
|
if (ex.original?.status !== 404) {
|
|
@@ -136,6 +150,7 @@ var AzureDevOpsApi = class {
|
|
|
136
150
|
}
|
|
137
151
|
}
|
|
138
152
|
if (issueResult != null) {
|
|
153
|
+
await this.requireWorkItemProject(provider, token, owner, projectName, issueResult, options.baseUrl, scope);
|
|
139
154
|
const issueType = issueResult.fields["System.WorkItemType"];
|
|
140
155
|
const state = issueResult.fields["System.State"];
|
|
141
156
|
const stateCategory = await this.getWorkItemStateCategory(issueType, state, provider, token, owner, projectName, options);
|
|
@@ -179,9 +194,10 @@ var AzureDevOpsApi = class {
|
|
|
179
194
|
}
|
|
180
195
|
async getIssue(provider, token, project, id, options) {
|
|
181
196
|
const scope = getScopedLogger();
|
|
197
|
+
const resource = await this.requireRestResource(provider, token, project.resourceName, options.baseUrl, "workItems", "6.0");
|
|
182
198
|
let issueResult;
|
|
183
199
|
try {
|
|
184
|
-
issueResult = await this.
|
|
200
|
+
issueResult = await this.getWorkItem(provider, token, project.resourceName, project.name, id, options.baseUrl, resource, scope);
|
|
185
201
|
} catch (ex) {
|
|
186
202
|
if (ex instanceof AuthenticationError) throw ex;
|
|
187
203
|
if (ex.original?.status !== 404) {
|
|
@@ -190,9 +206,10 @@ var AzureDevOpsApi = class {
|
|
|
190
206
|
}
|
|
191
207
|
}
|
|
192
208
|
if (issueResult != null) {
|
|
209
|
+
await this.requireWorkItemProject(provider, token, project.resourceName, project.name, issueResult, options.baseUrl, scope);
|
|
193
210
|
const issueType = issueResult.fields["System.WorkItemType"];
|
|
194
211
|
const state = issueResult.fields["System.State"];
|
|
195
|
-
const [stateCategory, htmlFields] = await Promise.all([this.getWorkItemStateCategory(issueType, state, provider, token, project.resourceName, project.name, options),
|
|
212
|
+
const [stateCategory, htmlFields] = await Promise.all([this.getWorkItemStateCategory(issueType, state, provider, token, project.resourceName, project.name, options), this.getWorkItemHtmlFields(provider, token, project.resourceName, options.baseUrl, issueResult.fields, scope)]);
|
|
196
213
|
return fromAzureWorkItem(issueResult, provider, project, stateCategory, "point", htmlFields);
|
|
197
214
|
}
|
|
198
215
|
}
|
|
@@ -258,18 +275,30 @@ var AzureDevOpsApi = class {
|
|
|
258
275
|
}
|
|
259
276
|
}
|
|
260
277
|
async getWorkItemStateCategory(issueType, state, provider, token, owner, projectName, options, cancellation) {
|
|
261
|
-
|
|
262
|
-
|
|
278
|
+
const states = await this.getWorkItemTypeStates(provider, token, owner, projectName, issueType, options.baseUrl, cancellation);
|
|
279
|
+
return resolveAzureWorkItemStateCategory(states, state);
|
|
280
|
+
}
|
|
281
|
+
getWorkItemTypeStates(provider, token, owner, project, type, baseUrl, cancellation) {
|
|
282
|
+
return this._workItemStates.getStates({
|
|
283
|
+
baseUrl,
|
|
263
284
|
namespace: owner,
|
|
264
|
-
project
|
|
285
|
+
project,
|
|
265
286
|
token: token.accessToken,
|
|
266
287
|
isPAT: true
|
|
267
|
-
},
|
|
288
|
+
}, type, async (signal) => {
|
|
289
|
+
const resource = await this.requireRestResource(provider, token, owner, baseUrl, "workItemTypeStates", "6.0-preview.1", signal);
|
|
290
|
+
return this.request(provider, token, baseUrl, getAzureWorkItemTypeStatesPath(owner, project, type, resource.apiVersion), { method: "GET" }, void 0, signal);
|
|
291
|
+
}, cancellation, async (signal) => {
|
|
292
|
+
const resource = await this.requireRestResource(provider, token, owner, baseUrl, "backlogConfiguration", "6.0-preview.1", signal);
|
|
293
|
+
const path = `${encodeAzurePathSegment(owner)}/${encodeAzurePathSegment(project)}/_apis/work/backlogconfiguration?api-version=${resource.apiVersion}`;
|
|
294
|
+
return this.request(provider, token, baseUrl, path, { method: "GET" }, void 0, signal);
|
|
295
|
+
});
|
|
268
296
|
}
|
|
269
297
|
async getRepositoryMetadata(provider, token, owner, repo, options, cancellation) {
|
|
270
298
|
const scope = getScopedLogger();
|
|
299
|
+
const resource = await this.requireRestResource(provider, token, owner, options.baseUrl, "repositories", "7.1", cancellation);
|
|
271
300
|
try {
|
|
272
|
-
const response = await this.getRepository(provider, token, owner, repo, options.baseUrl, scope, cancellation);
|
|
301
|
+
const response = await this.getRepository(provider, token, owner, repo, options.baseUrl, resource.apiVersion, scope, cancellation);
|
|
273
302
|
if (response == null) return void 0;
|
|
274
303
|
return {
|
|
275
304
|
provider,
|
|
@@ -289,8 +318,9 @@ var AzureDevOpsApi = class {
|
|
|
289
318
|
}
|
|
290
319
|
async getDefaultBranch(provider, token, owner, repo, options, cancellation) {
|
|
291
320
|
const scope = getScopedLogger();
|
|
321
|
+
const resource = await this.requireRestResource(provider, token, owner, options.baseUrl, "repositories", "7.1", cancellation);
|
|
292
322
|
try {
|
|
293
|
-
const response = await this.getRepository(provider, token, owner, repo, options.baseUrl, scope, cancellation);
|
|
323
|
+
const response = await this.getRepository(provider, token, owner, repo, options.baseUrl, resource.apiVersion, scope, cancellation);
|
|
294
324
|
if (response?.defaultBranch == null) return void 0;
|
|
295
325
|
return {
|
|
296
326
|
provider,
|
|
@@ -353,24 +383,28 @@ var AzureDevOpsApi = class {
|
|
|
353
383
|
const slice = ids.slice(offset, offset + pageSize);
|
|
354
384
|
const values = [];
|
|
355
385
|
if (slice.length > 0) {
|
|
356
|
-
const
|
|
386
|
+
const batch = await this.getRestResource(provider, token, collection, options.baseUrl, "workItemsBatch", "5.0", cancellation);
|
|
387
|
+
const resource = batch ?? await this.requireRestResource(provider, token, collection, options.baseUrl, "workItems", "5.0", cancellation);
|
|
388
|
+
const route = batch != null ? `workitemsbatch?api-version=${resource.apiVersion}` : `workitems?ids=${slice.join(",")}&$expand=Links&errorPolicy=Omit&api-version=${resource.apiVersion}`;
|
|
389
|
+
const workItems = await this.request(provider, token, options.baseUrl, `${encodeAzurePathSegment(collection)}/_apis/wit/${route}`, batch != null ? {
|
|
357
390
|
method: "POST",
|
|
358
391
|
body: JSON.stringify({
|
|
359
392
|
ids: slice,
|
|
360
393
|
$expand: "Links",
|
|
361
394
|
errorPolicy: "Omit"
|
|
362
395
|
})
|
|
363
|
-
}, scope, cancellation);
|
|
396
|
+
} : { method: "GET" }, scope, cancellation);
|
|
364
397
|
const byId = new Map((workItems?.value ?? []).filter((w) => w != null).map((w) => [w.id, w]));
|
|
365
|
-
const htmlFields = [...byId.values()].some((w) => needsAzureWorkItemHtmlFields(w.fields)) ? await this.getWorkItemHtmlFields(provider, token, options.baseUrl, collection, scope, cancellation) : void 0;
|
|
366
398
|
for (const id of slice) {
|
|
367
399
|
const workItem = byId.get(id);
|
|
368
400
|
if (workItem == null) continue;
|
|
369
401
|
const projectName = workItem.fields["System.TeamProject"];
|
|
402
|
+
if (options.projectNames?.length && !options.projectNames.some((name) => name.toLowerCase() === projectName?.toLowerCase())) throw new Error(`Azure DevOps work item ${id} is outside the requested projects`);
|
|
370
403
|
const project = options.resolveProject(projectName);
|
|
371
404
|
if (project == null) throw new Error(`Azure DevOps work item ${id} is in project '${projectName}', which isn't visible`);
|
|
372
405
|
if (cancellation?.aborted) throw new CancellationError();
|
|
373
406
|
const stateCategory = await this.getWorkItemStateCategory(workItem.fields["System.WorkItemType"], workItem.fields["System.State"], provider, token, collection, project.name, options, cancellation);
|
|
407
|
+
const htmlFields = await this.getWorkItemHtmlFields(provider, token, collection, options.baseUrl, workItem.fields, scope, cancellation);
|
|
374
408
|
values.push(fromAzureWorkItem(workItem, provider, project, stateCategory, "search", htmlFields));
|
|
375
409
|
}
|
|
376
410
|
}
|
|
@@ -428,7 +462,10 @@ var AzureDevOpsApi = class {
|
|
|
428
462
|
token: token.accessToken,
|
|
429
463
|
isPAT: true
|
|
430
464
|
};
|
|
431
|
-
return (await this._workItemStates.getTypes(scope,
|
|
465
|
+
return (await this._workItemStates.getTypes(scope, async (signal) => {
|
|
466
|
+
const resource = await this.requireRestResource(provider, token, collection, options.baseUrl, "workItemTypes", "6.0", signal);
|
|
467
|
+
return this.request(provider, token, void 0, getAzureWorkItemTypesUrl(options.baseUrl, collection, project, resource.apiVersion), { method: "GET" }, void 0, signal);
|
|
468
|
+
}, cancellation)).map((name) => ({
|
|
432
469
|
project,
|
|
433
470
|
name,
|
|
434
471
|
scope
|
|
@@ -437,7 +474,7 @@ var AzureDevOpsApi = class {
|
|
|
437
474
|
const states = await mapBounded(types, workItemMetadataConcurrency, async (type) => ({
|
|
438
475
|
name: type.name,
|
|
439
476
|
project: type.project,
|
|
440
|
-
states: await this.
|
|
477
|
+
states: requireAzureWorkItemStateCategories(await this.getWorkItemTypeStates(provider, token, collection, type.project, type.name, options.baseUrl, cancellation))
|
|
441
478
|
}));
|
|
442
479
|
workflows = new Map(projectNames.map((project) => [project, { types: states.filter((type) => type.project === project) }]));
|
|
443
480
|
}
|
|
@@ -446,13 +483,13 @@ var AzureDevOpsApi = class {
|
|
|
446
483
|
/**
|
|
447
484
|
* The ids a collection-level WIQL query matches, in its order.
|
|
448
485
|
*
|
|
449
|
-
* `
|
|
450
|
-
* answers; `timePrecision=true` is what lets the criteria's dates compare as instants — see `toWiqlDate`.
|
|
486
|
+
* `timePrecision=true` lets the criteria's dates compare as instants, including on legacy servers.
|
|
451
487
|
*/
|
|
452
488
|
async queryWorkItemIds(provider, token, collection, baseUrl, wiql, top, scope, cancellation, asOf) {
|
|
453
489
|
const query = asOf == null ? wiql : `${wiql} ASOF '${asOf}'`;
|
|
454
490
|
if (query.length > 32e3) throw new Error("Azure DevOps work item search query is too long; narrow the search");
|
|
455
|
-
const
|
|
491
|
+
const resource = await this.requireRestResource(provider, token, collection, baseUrl, "wiql", "5.0", cancellation);
|
|
492
|
+
const result = await this.request(provider, token, baseUrl, `${encodeAzurePathSegment(collection)}/_apis/wit/wiql?$top=${top}&timePrecision=true&api-version=${resource.apiVersion}`, {
|
|
456
493
|
method: "POST",
|
|
457
494
|
body: JSON.stringify({ query })
|
|
458
495
|
}, scope, cancellation);
|
|
@@ -462,35 +499,17 @@ var AzureDevOpsApi = class {
|
|
|
462
499
|
asOf: result.asOf
|
|
463
500
|
};
|
|
464
501
|
}
|
|
465
|
-
getRepository(provider, token, owner, repo, baseUrl, scope, cancellation) {
|
|
502
|
+
async getRepository(provider, token, owner, repo, baseUrl, apiVersion, scope, cancellation) {
|
|
466
503
|
const { projectName, repoName } = parseAzureRepositoryDescriptor(repo);
|
|
467
|
-
|
|
504
|
+
const encodedProject = encodeAzurePathSegment(projectName);
|
|
505
|
+
const encodedRepo = encodeAzurePathSegment(repoName);
|
|
506
|
+
return this.request(provider, token, baseUrl, `${encodeAzurePathSegment(owner)}/${encodedProject}/_apis/git/repositories/${encodedRepo}?api-version=${apiVersion}`, { method: "GET" }, scope, cancellation);
|
|
468
507
|
}
|
|
469
508
|
async toPullRequest(pr, provider, token, owner, baseUrl, scope, cancellation) {
|
|
470
509
|
const forkRepositoryUrls = await this.getForkRepositoryUrls(provider, token, owner, baseUrl, pr.forkSource?.repository, scope, cancellation);
|
|
471
510
|
return fromAzurePullRequest(pr, provider, owner, baseUrl, forkRepositoryUrls, "point");
|
|
472
511
|
}
|
|
473
512
|
/**
|
|
474
|
-
* The organization's rich text fields a work item's description may come from, for a work item none of the
|
|
475
|
-
* built-in description fields describes. Best-effort: a failed read leaves the description to those fields rather
|
|
476
|
-
* than failing the work item, so it is `undefined` on any failure but a cancellation. Logs to the caller's `scope`,
|
|
477
|
-
* captured before its first `await`: a scope read here, after the caller's reads, can be stale in a browser.
|
|
478
|
-
*/
|
|
479
|
-
async getWorkItemHtmlFields(provider, token, baseUrl, organization, scope, cancellation) {
|
|
480
|
-
try {
|
|
481
|
-
return await this._workItemStates.getHtmlFields({
|
|
482
|
-
baseUrl,
|
|
483
|
-
namespace: organization,
|
|
484
|
-
token: token.accessToken,
|
|
485
|
-
isPAT: true
|
|
486
|
-
}, (signal) => this.request(provider, token, baseUrl, getAzureWorkItemFieldsPath(organization), { method: "GET" }, void 0, signal), cancellation);
|
|
487
|
-
} catch (ex) {
|
|
488
|
-
if (isCancellationError(ex) && cancellation?.aborted) throw ex;
|
|
489
|
-
scope?.warn(`Unable to read the Azure DevOps field catalog of '${organization}': ${ex}`);
|
|
490
|
-
return;
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
/**
|
|
494
513
|
* Resolves the web and HTTPS clone URLs of the fork a cross-repository pull request comes from. Every other
|
|
495
514
|
* repository URL the model reports is rebuilt from the pull request payload; only a fork reference lacks the
|
|
496
515
|
* project to do that, so only a fork costs a request.
|
|
@@ -517,7 +536,9 @@ var AzureDevOpsApi = class {
|
|
|
517
536
|
}
|
|
518
537
|
async fetchForkRepositoryUrls(provider, token, owner, baseUrl, repositoryId, cacheable, scope, cancellation) {
|
|
519
538
|
try {
|
|
520
|
-
|
|
539
|
+
encodeAzurePathSegment(repositoryId);
|
|
540
|
+
const resource = await this.requireRestResource(provider, token, owner, baseUrl, "repositories", "4.1", cancellation);
|
|
541
|
+
const response = await this.request(provider, token, baseUrl, `${encodeAzurePathSegment(owner)}/_apis/git/repositories/${encodeAzurePathSegment(repositoryId)}?api-version=${resource.apiVersion}`, { method: "GET" }, scope, cancellation);
|
|
521
542
|
const webUrl = sanitizeAzureRepositoryUrl(response?.webUrl, baseUrl, owner);
|
|
522
543
|
const cloneHttps = sanitizeAzureRepositoryUrl(response?.remoteUrl, baseUrl, owner);
|
|
523
544
|
const url = webUrl ?? cloneHttps;
|
|
@@ -536,6 +557,66 @@ var AzureDevOpsApi = class {
|
|
|
536
557
|
return;
|
|
537
558
|
}
|
|
538
559
|
}
|
|
560
|
+
async getWorkItem(provider, token, owner, project, id, baseUrl, resource, scope) {
|
|
561
|
+
const encodedProject = encodeAzurePathSegment(project);
|
|
562
|
+
const encodedId = encodeAzurePathSegment(id);
|
|
563
|
+
const projectPath = resource.projectScoped ? `/${encodedProject}` : "";
|
|
564
|
+
return this.request(provider, token, baseUrl, `${encodeAzurePathSegment(owner)}${projectPath}/_apis/wit/workItems/${encodedId}?api-version=${resource.apiVersion}`, { method: "GET" }, scope);
|
|
565
|
+
}
|
|
566
|
+
async requireWorkItemProject(provider, token, owner, project, workItem, baseUrl, scope) {
|
|
567
|
+
const actualProject = workItem.fields?.["System.TeamProject"];
|
|
568
|
+
if (typeof actualProject !== "string" || !actualProject.trim()) throw new Error(`Azure DevOps work item ${workItem.id} has no project`);
|
|
569
|
+
if (actualProject.toLowerCase() === project.toLowerCase()) return;
|
|
570
|
+
if ((await this.request(provider, token, baseUrl, `${encodeAzurePathSegment(owner)}/_apis/projects/${encodeAzurePathSegment(project)}`, { method: "GET" }, scope))?.name?.toLowerCase() !== actualProject.toLowerCase()) throw new Error(`Azure DevOps work item ${workItem.id} is outside the requested project`);
|
|
571
|
+
}
|
|
572
|
+
async getWorkItemHtmlFields(provider, token, namespace, baseUrl, fields, scope, cancellation) {
|
|
573
|
+
try {
|
|
574
|
+
const requestToken = { ...token };
|
|
575
|
+
return await this._workItemDescriptions.getFields(fields, {
|
|
576
|
+
baseUrl,
|
|
577
|
+
namespace,
|
|
578
|
+
token: requestToken.accessToken,
|
|
579
|
+
isPAT: true
|
|
580
|
+
}, async (signal) => {
|
|
581
|
+
const resource = await this.requireRestResource(provider, requestToken, namespace, baseUrl, "fields", "6.0", signal);
|
|
582
|
+
return this.request(provider, requestToken, baseUrl, `${encodeAzurePathSegment(namespace)}/_apis/wit/fields?api-version=${resource.apiVersion}`, { method: "GET" }, void 0, signal);
|
|
583
|
+
}, cancellation);
|
|
584
|
+
} catch (ex) {
|
|
585
|
+
if (isCancellationError(ex) && cancellation?.aborted) throw ex;
|
|
586
|
+
scope?.warn(`Unable to read the Azure DevOps field catalog of '${namespace}': ${ex}`);
|
|
587
|
+
return [];
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
async getRestResource(provider, token, namespace, baseUrl, resource, version, cancellation) {
|
|
591
|
+
try {
|
|
592
|
+
if (cancellation?.aborted) throw new CancellationError();
|
|
593
|
+
encodeAzurePathSegment(namespace);
|
|
594
|
+
const discovery = this.config.wrapForForcedInsecureSSL(provider.getIgnoreSSLErrors(), () => this.restApi.getRestApiResource({
|
|
595
|
+
namespace,
|
|
596
|
+
resource,
|
|
597
|
+
version
|
|
598
|
+
}, {
|
|
599
|
+
token: token.accessToken,
|
|
600
|
+
isPAT: true,
|
|
601
|
+
baseUrl
|
|
602
|
+
}));
|
|
603
|
+
if (cancellation?.aborted) discovery.catch(() => {});
|
|
604
|
+
return await (cancellation != null ? raceWithSignal(discovery, cancellation) : discovery);
|
|
605
|
+
} catch (ex) {
|
|
606
|
+
return throwProviderError(token, ex);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
async requireRestResource(provider, token, namespace, baseUrl, resource, version, cancellation) {
|
|
610
|
+
let result;
|
|
611
|
+
try {
|
|
612
|
+
result = await this.getRestResource(provider, token, namespace, baseUrl, resource, version, cancellation);
|
|
613
|
+
} catch (ex) {
|
|
614
|
+
if (ex instanceof RequestNotFoundError) throw new Error("Azure DevOps REST resource discovery failed", { cause: ex });
|
|
615
|
+
throw ex;
|
|
616
|
+
}
|
|
617
|
+
if (result == null) throw new Error(`Azure DevOps REST resource ${resource} is unavailable`);
|
|
618
|
+
return result;
|
|
619
|
+
}
|
|
539
620
|
async request(provider, token, baseUrl, route, options, scope, cancellation) {
|
|
540
621
|
const { accessToken } = token;
|
|
541
622
|
const url = baseUrl ? `${baseUrl}/${route}` : route;
|
|
@@ -670,8 +751,8 @@ __decorate([trace({ args: (provider, token, collection) => ({
|
|
|
670
751
|
collection
|
|
671
752
|
}) })], AzureDevOpsApi.prototype, "countWorkItems", null);
|
|
672
753
|
/** Wires an {@link AzureDevOpsApi} from the full runtime context, mapping `ctx` down to the narrow config. */
|
|
673
|
-
function createAzureDevOpsApi(ctx, workItemStates) {
|
|
674
|
-
return new AzureDevOpsApi(baseProviderApiConfig(ctx), workItemStates);
|
|
754
|
+
function createAzureDevOpsApi(ctx, workItemStates, workItemDescriptions) {
|
|
755
|
+
return new AzureDevOpsApi(baseProviderApiConfig(ctx), workItemStates, workItemDescriptions);
|
|
675
756
|
}
|
|
676
757
|
//#endregion
|
|
677
758
|
export { AzureDevOpsApi, createAzureDevOpsApi };
|