@gitkraken/core-gitlens 0.20.0 → 0.20.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.
@@ -1,3 +1,4 @@
1
+ import { CancellationError } from "../../utils/cancellation.js";
1
2
  import { getScopedLogger } from "../../utils/logger.scoped.js";
2
3
  import { debug } from "../../utils/decorators/log.js";
3
4
  import __decorate from "../../_virtual/@oxc-project+runtime/helpers/esm/decorate.js";
@@ -7,6 +8,40 @@ import { RemotesGitProviderBase } from "../../git/providers/shared/remotes.js";
7
8
  import { createRemoteProviderMatcher } from "../../git/remotes/matcher.js";
8
9
  import { parseGitRemotes } from "../parsers/remoteParser.js";
9
10
  //#region ../git-cli/src/providers/remotes.ts
11
+ /** Long enough for a slow host to answer, short enough that a blackholed one doesn't stall the wizard */
12
+ const probeRemoteTimeoutMs = 5e3;
13
+ /**
14
+ * Keeps the probe from asking anyone for credentials: an empty `GIT_ASKPASS` stops git's askpass lookup
15
+ * outright (it doesn't fall through to `core.askPass` or `SSH_ASKPASS`), so the editor's askpass can't
16
+ * open a credential prompt over the wizard, and `GIT_TERMINAL_PROMPT=0` refuses the tty fallback.
17
+ * Non-interactive credential helpers still run, so a stored credential still authenticates.
18
+ */
19
+ const probeRemoteEnv = {
20
+ GIT_ASKPASS: "",
21
+ GIT_TERMINAL_PROMPT: "0",
22
+ GCM_INTERACTIVE: "NEVER",
23
+ SSH_ASKPASS: ""
24
+ };
25
+ function getProbeFailureReason(stderr) {
26
+ if (/Could not resolve host|nodename nor servname|Name or service not known|No such host/i.test(stderr)) return "hostNotFound";
27
+ if (/Host key verification failed/i.test(stderr)) return "hostKeyUnverified";
28
+ if (/could not read (?:Username|Password)|terminal prompts disabled|Authentication failed|Permission denied|returned error: 40[13]\b/i.test(stderr)) return "authRequired";
29
+ if (/Repository not found|repository '.*' not found|does not appear to be a git repository|returned error: 404\b/i.test(stderr)) return "notFound";
30
+ return "other";
31
+ }
32
+ /** SSH's generic tail, which follows (and buries) the host's own explanation of the failure */
33
+ const genericProbeFailureLine = /^(?:fatal:\s*)?(?:Could not read from remote repository|Please make sure you have the correct access rights|and the repository exists)/;
34
+ /**
35
+ * The line of stderr that names what went wrong most plainly: SSH's generic trailer is dropped first so the host's
36
+ * message before it (e.g. `ERROR: Repository not found.`) can win; then the last `fatal:` line (prefix stripped),
37
+ * else the last line. If only the generic trailer remains, it is used rather than returning nothing.
38
+ */
39
+ function getProbeFailureMessage(stderr) {
40
+ const lines = stderr.split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length);
41
+ const specific = lines.filter((l) => !genericProbeFailureLine.test(l));
42
+ const candidates = specific.length ? specific : lines;
43
+ return (candidates.findLast((l) => l.startsWith("fatal:")) ?? candidates.at(-1))?.replace(/^fatal:\s*/, "") || void 0;
44
+ }
10
45
  var RemotesGitSubProvider = class extends RemotesGitProviderBase {
11
46
  git;
12
47
  constructor(context, git, cache, provider) {
@@ -42,11 +77,16 @@ var RemotesGitSubProvider = class extends RemotesGitProviderBase {
42
77
  return remotes;
43
78
  }
44
79
  async addRemote(repoPath, name, url, options) {
80
+ if (!options?.fetch) {
81
+ await this.git.run({ cwd: repoPath }, "remote", "add", name, url);
82
+ this.context.hooks?.cache?.onReset?.(repoPath, "remotes");
83
+ this.context.hooks?.repository?.onChanged?.(repoPath, ["config", "remotes"]);
84
+ return;
85
+ }
45
86
  try {
46
- await this.git.run({ cwd: repoPath }, "remote", "add", options?.fetch ? "-f" : void 0, name, url);
87
+ await this.git.run({ cwd: repoPath }, "remote", "add", "-f", name, url);
47
88
  } finally {
48
- if (options?.fetch) this.context.hooks?.cache?.onReset?.(repoPath, "remotes", "branches");
49
- else this.context.hooks?.cache?.onReset?.(repoPath, "remotes");
89
+ this.context.hooks?.cache?.onReset?.(repoPath, "remotes", "branches");
50
90
  this.context.hooks?.repository?.onChanged?.(repoPath, ["config", "remotes"]);
51
91
  }
52
92
  }
@@ -55,6 +95,40 @@ var RemotesGitSubProvider = class extends RemotesGitProviderBase {
55
95
  const [remote] = await this.getRemotes(repoPath, { filter: (r) => r.url === url });
56
96
  return remote;
57
97
  }
98
+ async probeRemote(repoPath, url, cancellation) {
99
+ if (url.startsWith("-")) return {
100
+ reachable: false,
101
+ reason: "other"
102
+ };
103
+ const timeoutSignal = AbortSignal.timeout(probeRemoteTimeoutMs);
104
+ const signal = cancellation != null ? AbortSignal.any([cancellation, timeoutSignal]) : timeoutSignal;
105
+ const result = await this.git.run({
106
+ cwd: repoPath,
107
+ cancellation: signal,
108
+ errors: "ignore",
109
+ env: probeRemoteEnv,
110
+ priority: "interactive"
111
+ }, "ls-remote", url, "HEAD");
112
+ const { completion } = result;
113
+ if (completion.status === "exited" && completion.code === 0) return { reachable: true };
114
+ if (completion.status === "cancelled") {
115
+ if (cancellation?.aborted) throw new CancellationError(completion.error, "aborted");
116
+ return {
117
+ reachable: false,
118
+ reason: "timeout"
119
+ };
120
+ }
121
+ if (completion.status === "failed") {
122
+ if (cancellation?.aborted) throw new CancellationError(completion.error, "aborted");
123
+ throw completion.error;
124
+ }
125
+ const stderr = typeof result.stderr === "string" ? result.stderr : "";
126
+ return {
127
+ reachable: false,
128
+ reason: getProbeFailureReason(stderr),
129
+ message: getProbeFailureMessage(stderr)
130
+ };
131
+ }
58
132
  async pruneRemote(repoPath, name) {
59
133
  try {
60
134
  await this.git.run({ cwd: repoPath }, "remote", "prune", name);
@@ -78,9 +152,10 @@ __decorate([debug({
78
152
  })], RemotesGitSubProvider.prototype, "getRemotes", null);
79
153
  __decorate([gate(), debug()], RemotesGitSubProvider.prototype, "addRemote", null);
80
154
  __decorate([gate(), debug()], RemotesGitSubProvider.prototype, "addRemoteWithResult", null);
155
+ __decorate([debug({ args: (repoPath) => ({ repoPath }) })], RemotesGitSubProvider.prototype, "probeRemote", null);
81
156
  __decorate([gate(), debug()], RemotesGitSubProvider.prototype, "pruneRemote", null);
82
157
  __decorate([gate(), debug()], RemotesGitSubProvider.prototype, "removeRemote", null);
83
158
  //#endregion
84
- export { RemotesGitSubProvider };
159
+ export { RemotesGitSubProvider, getProbeFailureMessage, getProbeFailureReason };
85
160
 
86
161
  //# sourceMappingURL=remotes.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"remotes.js","names":[],"sources":["../../../../git-cli/src/providers/remotes.ts"],"sourcesContent":["import type { Cache } from '@gitlens/git/cache.js';\nimport type { GitServiceContext } from '@gitlens/git/context.js';\nimport type { GitRemote } from '@gitlens/git/models/remote.js';\nimport type { GitRemotesSubProvider } from '@gitlens/git/providers/remotes.js';\nimport { RemotesGitProviderBase } from '@gitlens/git/providers/shared/remotes.js';\nimport { createRemoteProviderMatcher } from '@gitlens/git/remotes/matcher.js';\nimport { sortRemotes } from '@gitlens/git/utils/sorting.js';\nimport { gate } from '@gitlens/utils/decorators/gate.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport type { CliGitProviderInternal } from '../cliGitProvider.js';\nimport type { Git } from '../exec/git.js';\nimport { parseGitRemotes } from '../parsers/remoteParser.js';\n\nexport class RemotesGitSubProvider extends RemotesGitProviderBase implements GitRemotesSubProvider {\n\tconstructor(\n\t\tcontext: GitServiceContext,\n\t\tprivate readonly git: Git,\n\t\tcache: Cache,\n\t\tprovider: CliGitProviderInternal,\n\t) {\n\t\tsuper(context, cache, provider);\n\t}\n\n\t@debug({ quiet: true, args: repoPath => ({ repoPath: repoPath }) })\n\tasync getRemotes(\n\t\trepoPath: string | undefined,\n\t\toptions?: { filter?: (remote: GitRemote) => boolean; sort?: boolean },\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitRemote[]> {\n\t\tif (repoPath == null) return [];\n\n\t\tconst scope = getScopedLogger();\n\n\t\tlet remotes = await this.cache.getRemotes(\n\t\t\trepoPath,\n\t\t\tasync (commonPath, cacheable, signal) => {\n\t\t\t\t// Prefer the aggregate signal from the cache; fall back to the caller's cancellation.\n\t\t\t\tsignal ??= cancellation;\n\t\t\t\tconst configs = await this.context.remotes?.getCustomProviders?.(repoPath);\n\t\t\t\tconst remoteProviderMatcher = createRemoteProviderMatcher(configs, this.context.remotes);\n\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await this.git.run(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\t\t\tcancellation: signal,\n\t\t\t\t\t\t\tcaching: { cache: this.cache.gitResults, commonPath: commonPath },\n\t\t\t\t\t\t},\n\t\t\t\t\t\t'remote',\n\t\t\t\t\t\t'-v',\n\t\t\t\t\t);\n\n\t\t\t\t\t// Fetch default remote name from GK config before parsing so it's set at construction time\n\t\t\t\t\tconst defaultName = await this.provider.config.getGkConfig?.(repoPath, 'gk.defaultRemote');\n\t\t\t\t\tconst remotes = parseGitRemotes(result.stdout, commonPath, remoteProviderMatcher, defaultName);\n\n\t\t\t\t\treturn remotes;\n\t\t\t\t} catch (ex) {\n\t\t\t\t\tcacheable.invalidate();\n\t\t\t\t\tscope?.error(ex);\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\n\t\tif (options?.filter != null) {\n\t\t\tremotes = remotes.filter(options.filter);\n\t\t}\n\n\t\tif (options?.sort) {\n\t\t\tsortRemotes(remotes);\n\t\t}\n\n\t\treturn remotes;\n\t}\n\n\t@gate()\n\t@debug()\n\tasync addRemote(repoPath: string, name: string, url: string, options?: { fetch?: boolean }): Promise<void> {\n\t\ttry {\n\t\t\tawait this.git.run({ cwd: repoPath }, 'remote', 'add', options?.fetch ? '-f' : undefined, name, url);\n\t\t} finally {\n\t\t\t// A fetch creates the remote's tracking branches, which the branch, ref and history caches hold. The\n\t\t\t// remote is added before the fetch runs, so a failed `-f` still leaves it behind.\n\t\t\tif (options?.fetch) {\n\t\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'remotes', 'branches');\n\t\t\t} else {\n\t\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'remotes');\n\t\t\t}\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['config', 'remotes']);\n\t\t}\n\t}\n\n\t@gate()\n\t@debug()\n\tasync addRemoteWithResult(\n\t\trepoPath: string,\n\t\tname: string,\n\t\turl: string,\n\t\toptions?: { fetch?: boolean },\n\t): Promise<GitRemote | undefined> {\n\t\tawait this.addRemote(repoPath, name, url, options);\n\t\tconst [remote] = await this.getRemotes(repoPath, { filter: r => r.url === url });\n\t\treturn remote;\n\t}\n\n\t@gate()\n\t@debug()\n\tasync pruneRemote(repoPath: string, name: string): Promise<void> {\n\t\ttry {\n\t\t\tawait this.git.run({ cwd: repoPath }, 'remote', 'prune', name);\n\t\t} finally {\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'remotes', 'branches');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['remotes']);\n\t\t}\n\t}\n\n\t@gate()\n\t@debug()\n\tasync removeRemote(repoPath: string, name: string): Promise<void> {\n\t\ttry {\n\t\t\tawait this.git.run({ cwd: repoPath }, 'remote', 'remove', name);\n\t\t} finally {\n\t\t\t// Removing a remote deletes its tracking branches too\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'remotes', 'branches');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['config', 'remotes']);\n\t\t}\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"remotes.js","names":[],"sources":["../../../../git-cli/src/providers/remotes.ts"],"sourcesContent":["import type { Cache } from '@gitlens/git/cache.js';\nimport type { GitServiceContext } from '@gitlens/git/context.js';\nimport type { GitRemote } from '@gitlens/git/models/remote.js';\nimport type {\n\tGitRemoteProbeFailureReason,\n\tGitRemoteProbeResult,\n\tGitRemotesSubProvider,\n} from '@gitlens/git/providers/remotes.js';\nimport { RemotesGitProviderBase } from '@gitlens/git/providers/shared/remotes.js';\nimport { createRemoteProviderMatcher } from '@gitlens/git/remotes/matcher.js';\nimport { sortRemotes } from '@gitlens/git/utils/sorting.js';\nimport { CancellationError } from '@gitlens/utils/cancellation.js';\nimport { gate } from '@gitlens/utils/decorators/gate.js';\nimport { debug } from '@gitlens/utils/decorators/log.js';\nimport { getScopedLogger } from '@gitlens/utils/logger.scoped.js';\nimport type { CliGitProviderInternal } from '../cliGitProvider.js';\nimport type { Git } from '../exec/git.js';\nimport { parseGitRemotes } from '../parsers/remoteParser.js';\n\n/** Long enough for a slow host to answer, short enough that a blackholed one doesn't stall the wizard */\nconst probeRemoteTimeoutMs = 5000;\n\n/**\n * Keeps the probe from asking anyone for credentials: an empty `GIT_ASKPASS` stops git's askpass lookup\n * outright (it doesn't fall through to `core.askPass` or `SSH_ASKPASS`), so the editor's askpass can't\n * open a credential prompt over the wizard, and `GIT_TERMINAL_PROMPT=0` refuses the tty fallback.\n * Non-interactive credential helpers still run, so a stored credential still authenticates.\n */\nconst probeRemoteEnv: Record<string, string> = {\n\tGIT_ASKPASS: '',\n\tGIT_TERMINAL_PROMPT: '0',\n\tGCM_INTERACTIVE: 'NEVER',\n\tSSH_ASKPASS: '',\n};\n\nexport function getProbeFailureReason(stderr: string): GitRemoteProbeFailureReason {\n\tif (/Could not resolve host|nodename nor servname|Name or service not known|No such host/i.test(stderr)) {\n\t\treturn 'hostNotFound';\n\t}\n\t// Checked before auth: the probe forbids ssh's prompt to trust an unknown host, so a correct URL on a host\n\t// not yet in known_hosts fails here, and that isn't an authentication problem\n\tif (/Host key verification failed/i.test(stderr)) {\n\t\treturn 'hostKeyUnverified';\n\t}\n\t// HTTP statuses are matched on git's own wording so digits elsewhere (e.g. a `/403/` URL path) don't count\n\tif (\n\t\t/could not read (?:Username|Password)|terminal prompts disabled|Authentication failed|Permission denied|returned error: 40[13]\\b/i.test(\n\t\t\tstderr,\n\t\t)\n\t) {\n\t\treturn 'authRequired';\n\t}\n\tif (\n\t\t/Repository not found|repository '.*' not found|does not appear to be a git repository|returned error: 404\\b/i.test(\n\t\t\tstderr,\n\t\t)\n\t) {\n\t\treturn 'notFound';\n\t}\n\treturn 'other';\n}\n\n/** SSH's generic tail, which follows (and buries) the host's own explanation of the failure */\nconst genericProbeFailureLine =\n\t/^(?:fatal:\\s*)?(?:Could not read from remote repository|Please make sure you have the correct access rights|and the repository exists)/;\n\n/**\n * The line of stderr that names what went wrong most plainly: SSH's generic trailer is dropped first so the host's\n * message before it (e.g. `ERROR: Repository not found.`) can win; then the last `fatal:` line (prefix stripped),\n * else the last line. If only the generic trailer remains, it is used rather than returning nothing.\n */\nexport function getProbeFailureMessage(stderr: string): string | undefined {\n\tconst lines = stderr\n\t\t.split(/\\r?\\n/)\n\t\t.map(l => l.trim())\n\t\t.filter(l => l.length);\n\tconst specific = lines.filter(l => !genericProbeFailureLine.test(l));\n\tconst candidates = specific.length ? specific : lines;\n\tconst fatal = candidates.findLast(l => l.startsWith('fatal:'));\n\treturn (fatal ?? candidates.at(-1))?.replace(/^fatal:\\s*/, '') || undefined;\n}\n\nexport class RemotesGitSubProvider extends RemotesGitProviderBase implements GitRemotesSubProvider {\n\tconstructor(\n\t\tcontext: GitServiceContext,\n\t\tprivate readonly git: Git,\n\t\tcache: Cache,\n\t\tprovider: CliGitProviderInternal,\n\t) {\n\t\tsuper(context, cache, provider);\n\t}\n\n\t@debug({ quiet: true, args: repoPath => ({ repoPath: repoPath }) })\n\tasync getRemotes(\n\t\trepoPath: string | undefined,\n\t\toptions?: { filter?: (remote: GitRemote) => boolean; sort?: boolean },\n\t\tcancellation?: AbortSignal,\n\t): Promise<GitRemote[]> {\n\t\tif (repoPath == null) return [];\n\n\t\tconst scope = getScopedLogger();\n\n\t\tlet remotes = await this.cache.getRemotes(\n\t\t\trepoPath,\n\t\t\tasync (commonPath, cacheable, signal) => {\n\t\t\t\t// Prefer the aggregate signal from the cache; fall back to the caller's cancellation.\n\t\t\t\tsignal ??= cancellation;\n\t\t\t\tconst configs = await this.context.remotes?.getCustomProviders?.(repoPath);\n\t\t\t\tconst remoteProviderMatcher = createRemoteProviderMatcher(configs, this.context.remotes);\n\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await this.git.run(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\t\t\tcancellation: signal,\n\t\t\t\t\t\t\tcaching: { cache: this.cache.gitResults, commonPath: commonPath },\n\t\t\t\t\t\t},\n\t\t\t\t\t\t'remote',\n\t\t\t\t\t\t'-v',\n\t\t\t\t\t);\n\n\t\t\t\t\t// Fetch default remote name from GK config before parsing so it's set at construction time\n\t\t\t\t\tconst defaultName = await this.provider.config.getGkConfig?.(repoPath, 'gk.defaultRemote');\n\t\t\t\t\tconst remotes = parseGitRemotes(result.stdout, commonPath, remoteProviderMatcher, defaultName);\n\n\t\t\t\t\treturn remotes;\n\t\t\t\t} catch (ex) {\n\t\t\t\t\tcacheable.invalidate();\n\t\t\t\t\tscope?.error(ex);\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\n\t\tif (options?.filter != null) {\n\t\t\tremotes = remotes.filter(options.filter);\n\t\t}\n\n\t\tif (options?.sort) {\n\t\t\tsortRemotes(remotes);\n\t\t}\n\n\t\treturn remotes;\n\t}\n\n\t@gate()\n\t@debug()\n\tasync addRemote(repoPath: string, name: string, url: string, options?: { fetch?: boolean }): Promise<void> {\n\t\tif (!options?.fetch) {\n\t\t\tawait this.git.run({ cwd: repoPath }, 'remote', 'add', name, url);\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'remotes');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['config', 'remotes']);\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tawait this.git.run({ cwd: repoPath }, 'remote', 'add', '-f', name, url);\n\t\t} finally {\n\t\t\t// Reset even on failure: `remote add -f` keeps the remote when only its fetch fails, and a\n\t\t\t// caller checking whether the remote now exists must not read the pre-add cache.\n\t\t\t// A fetch creates the remote's tracking branches, which the branch, ref and history caches hold\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'remotes', 'branches');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['config', 'remotes']);\n\t\t}\n\t}\n\n\t@gate()\n\t@debug()\n\tasync addRemoteWithResult(\n\t\trepoPath: string,\n\t\tname: string,\n\t\turl: string,\n\t\toptions?: { fetch?: boolean },\n\t): Promise<GitRemote | undefined> {\n\t\tawait this.addRemote(repoPath, name, url, options);\n\t\tconst [remote] = await this.getRemotes(repoPath, { filter: r => r.url === url });\n\t\treturn remote;\n\t}\n\n\t// The URL is left out of the log — it can carry credentials (`https://<token>@host/...`)\n\t@debug({ args: repoPath => ({ repoPath: repoPath }) })\n\tasync probeRemote(repoPath: string, url: string, cancellation?: AbortSignal): Promise<GitRemoteProbeResult> {\n\t\t// A leading `-` would be parsed as an option rather than the repository to query\n\t\tif (url.startsWith('-')) return { reachable: false, reason: 'other' };\n\n\t\tconst timeoutSignal = AbortSignal.timeout(probeRemoteTimeoutMs);\n\t\tconst signal = cancellation != null ? AbortSignal.any([cancellation, timeoutSignal]) : timeoutSignal;\n\n\t\tconst result = await this.git.run(\n\t\t\t{ cwd: repoPath, cancellation: signal, errors: 'ignore', env: probeRemoteEnv, priority: 'interactive' },\n\t\t\t// No `--exit-code`: a freshly created, empty repository advertises no HEAD but is a valid remote\n\t\t\t'ls-remote',\n\t\t\turl,\n\t\t\t'HEAD',\n\t\t);\n\n\t\tconst { completion } = result;\n\t\tif (completion.status === 'exited' && completion.code === 0) return { reachable: true };\n\n\t\tif (completion.status === 'cancelled') {\n\t\t\tif (cancellation?.aborted) throw new CancellationError(completion.error, 'aborted');\n\n\t\t\treturn { reachable: false, reason: 'timeout' };\n\t\t}\n\n\t\t// A run that never exited (spawn failure, missing binary, queue rejection) says nothing about the remote;\n\t\t// throw so callers treat it as unprobed rather than unreachable\n\t\tif (completion.status === 'failed') {\n\t\t\tif (cancellation?.aborted) throw new CancellationError(completion.error, 'aborted');\n\n\t\t\tthrow completion.error;\n\t\t}\n\n\t\t// Under `errors: 'ignore'` a non-zero exit resolves with its stderr; a run that never exited has none\n\t\tconst stderr = typeof result.stderr === 'string' ? result.stderr : '';\n\t\treturn {\n\t\t\treachable: false,\n\t\t\treason: getProbeFailureReason(stderr),\n\t\t\tmessage: getProbeFailureMessage(stderr),\n\t\t};\n\t}\n\n\t@gate()\n\t@debug()\n\tasync pruneRemote(repoPath: string, name: string): Promise<void> {\n\t\ttry {\n\t\t\tawait this.git.run({ cwd: repoPath }, 'remote', 'prune', name);\n\t\t} finally {\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'remotes', 'branches');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['remotes']);\n\t\t}\n\t}\n\n\t@gate()\n\t@debug()\n\tasync removeRemote(repoPath: string, name: string): Promise<void> {\n\t\ttry {\n\t\t\tawait this.git.run({ cwd: repoPath }, 'remote', 'remove', name);\n\t\t} finally {\n\t\t\t// Removing a remote deletes its tracking branches too\n\t\t\tthis.context.hooks?.cache?.onReset?.(repoPath, 'remotes', 'branches');\n\t\t\tthis.context.hooks?.repository?.onChanged?.(repoPath, ['config', 'remotes']);\n\t\t}\n\t}\n}\n"],"mappings":"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"}
@@ -16,9 +16,9 @@ export type AzureWorkItemStatesScope = {
16
16
  token: string;
17
17
  isPAT: boolean;
18
18
  };
19
- export declare function getAzureWorkItemTypesUrl(baseUrl: string, namespace: string, project: string, apiVersion?: string): string;
20
- export declare function getAzureWorkItemTypeStatesPath(namespace: string, project: string, type: string, apiVersion?: string): string;
21
- export declare function getAzureWorkItemTypeStatesUrl(baseUrl: string, namespace: string, project: string, type: string, apiVersion?: string): string;
19
+ export declare function getAzureWorkItemTypesUrl(baseUrl: string, namespace: string, project: string, apiVersion: string): string;
20
+ export declare function getAzureWorkItemTypeStatesPath(namespace: string, project: string, type: string, apiVersion: string): string;
21
+ export declare function getAzureWorkItemTypeStatesUrl(baseUrl: string, namespace: string, project: string, type: string, apiVersion: string): string;
22
22
  export declare function resolveAzureWorkItemStateCategory(snapshot: WorkItemTypeStatesSnapshot, state: string): AzureWorkItemStateCategory | undefined;
23
23
  export declare function requireAzureWorkItemStateCategories(snapshot: WorkItemTypeStatesSnapshot): NonNullable<AzureWorkItemTypeStates['types'][number]['states']>;
24
24
  /**
@@ -2,13 +2,13 @@ import { isCancellationError } from "../../../../utils/cancellation.js";
2
2
  import { PromiseCache } from "../../../../utils/promiseCache.js";
3
3
  import { azureIssueStateCategory, encodeAzurePathSegment } from "./models.js";
4
4
  //#region ../plus/integrations/src/providers/azure/workItemStateCategories.ts
5
- function getAzureWorkItemTypesUrl(baseUrl, namespace, project, apiVersion = "6.0") {
5
+ function getAzureWorkItemTypesUrl(baseUrl, namespace, project, apiVersion) {
6
6
  return `${baseUrl.replace(/\/$/, "")}/${encodeAzurePathSegment(namespace)}/${encodeAzurePathSegment(project)}/_apis/wit/workItemTypes?api-version=${apiVersion}`;
7
7
  }
8
- function getAzureWorkItemTypeStatesPath(namespace, project, type, apiVersion = "6.0-preview.1") {
8
+ function getAzureWorkItemTypeStatesPath(namespace, project, type, apiVersion) {
9
9
  return `${encodeAzurePathSegment(namespace)}/${encodeAzurePathSegment(project)}/_apis/wit/workItemTypes/${encodeAzurePathSegment(type)}/states?api-version=${apiVersion}`;
10
10
  }
11
- function getAzureWorkItemTypeStatesUrl(baseUrl, namespace, project, type, apiVersion = "6.0-preview.1") {
11
+ function getAzureWorkItemTypeStatesUrl(baseUrl, namespace, project, type, apiVersion) {
12
12
  return `${baseUrl.replace(/\/$/, "")}/${getAzureWorkItemTypeStatesPath(namespace, project, type, apiVersion)}`;
13
13
  }
14
14
  function parseWorkItemTypes(body) {
@@ -1 +1 @@
1
- {"version":3,"file":"workItemStateCategories.js","names":[],"sources":["../../../../../../plus/integrations/src/providers/azure/workItemStateCategories.ts"],"sourcesContent":["import type { AzureWorkItemTypeStates } from '@gitkraken/provider-apis';\nimport { isCancellationError } from '@gitlens/utils/cancellation.js';\nimport { PromiseCache } from '@gitlens/utils/promiseCache.js';\nimport type { AzureWorkItemStateCategory } from './models.js';\nimport { azureIssueStateCategory, encodeAzurePathSegment } from './models.js';\n\ntype WorkItemTypeStates = readonly { name: string; category?: string }[];\ntype WorkItemTypeStatesSnapshot = {\n\tstates: WorkItemTypeStates;\n\tusesLegacyMappings: boolean;\n};\ntype WorkItemStateMappings = ReadonlyMap<string, ReadonlyMap<string, string>>;\n\nexport type AzureWorkItemStatesScope = {\n\tbaseUrl: string;\n\tnamespace: string;\n\tproject: string;\n\ttoken: string;\n\tisPAT: boolean;\n};\n\nexport function getAzureWorkItemTypesUrl(\n\tbaseUrl: string,\n\tnamespace: string,\n\tproject: string,\n\tapiVersion = '6.0',\n): string {\n\treturn `${baseUrl.replace(/\\/$/, '')}/${encodeAzurePathSegment(namespace)}/${encodeAzurePathSegment(project)}/_apis/wit/workItemTypes?api-version=${apiVersion}`;\n}\n\n// Server 2020 serves this endpoint only as a preview; Services accepts the same version.\nexport function getAzureWorkItemTypeStatesPath(\n\tnamespace: string,\n\tproject: string,\n\ttype: string,\n\tapiVersion = '6.0-preview.1',\n): string {\n\treturn `${encodeAzurePathSegment(namespace)}/${encodeAzurePathSegment(project)}/_apis/wit/workItemTypes/${encodeAzurePathSegment(type)}/states?api-version=${apiVersion}`;\n}\n\nexport function getAzureWorkItemTypeStatesUrl(\n\tbaseUrl: string,\n\tnamespace: string,\n\tproject: string,\n\ttype: string,\n\tapiVersion = '6.0-preview.1',\n): string {\n\treturn `${baseUrl.replace(/\\/$/, '')}/${getAzureWorkItemTypeStatesPath(namespace, project, type, apiVersion)}`;\n}\n\nfunction parseWorkItemTypes(body: unknown): string[] {\n\tconst types = (body as { value?: unknown } | null)?.value;\n\tif (!Array.isArray(types)) throw new Error('Azure DevOps returned no work item types');\n\n\tconst names: string[] = [];\n\tfor (const type of types as { name?: unknown }[]) {\n\t\tif (typeof type?.name !== 'string' || !type.name.trim()) {\n\t\t\tthrow new Error('Azure DevOps returned an invalid work item type');\n\t\t}\n\n\t\tnames.push(type.name);\n\t}\n\treturn [...new Set(names)];\n}\n\nfunction parseWorkItemStates(body: unknown, allowMissingCategory = false): WorkItemTypeStates {\n\tconst states = (body as { value?: unknown } | null)?.value;\n\tif (!Array.isArray(states) || states.length === 0) throw new Error('Azure DevOps returned no work item states');\n\n\tconst parsed: { name: string; category?: string }[] = [];\n\tfor (const state of states as { name?: unknown; category?: unknown }[]) {\n\t\tif (\n\t\t\ttypeof state?.name !== 'string' ||\n\t\t\t!state.name.trim() ||\n\t\t\t(state.category === undefined\n\t\t\t\t? !allowMissingCategory\n\t\t\t\t: typeof state.category !== 'string' ||\n\t\t\t\t\tazureIssueStateCategory(state.category as AzureWorkItemStateCategory) == null) ||\n\t\t\tparsed.some(s => s.name === state.name && s.category !== state.category)\n\t\t) {\n\t\t\tthrow new Error('Azure DevOps returned an invalid work item state');\n\t\t}\n\n\t\tparsed.push({ name: state.name, category: state.category as string | undefined });\n\t}\n\treturn parsed;\n}\n\nexport function resolveAzureWorkItemStateCategory(\n\tsnapshot: WorkItemTypeStatesSnapshot,\n\tstate: string,\n): AzureWorkItemStateCategory | undefined {\n\tconst matched = snapshot.states.find(s => s.name === state);\n\tconst category = matched?.category as AzureWorkItemStateCategory | undefined;\n\tif ((snapshot.usesLegacyMappings || matched != null) && category == null) {\n\t\tthrow new Error(`Azure DevOps does not expose a category for work item state '${state}'`);\n\t}\n\n\treturn category;\n}\n\nexport function requireAzureWorkItemStateCategories(\n\tsnapshot: WorkItemTypeStatesSnapshot,\n): NonNullable<AzureWorkItemTypeStates['types'][number]['states']> {\n\treturn snapshot.states.map(state => {\n\t\tif (state.category == null) throw new Error('Azure DevOps does not expose a category for this work item state');\n\n\t\treturn { name: state.name, category: state.category };\n\t});\n}\n\nfunction parseWorkItemStateMappings(body: unknown): WorkItemStateMappings {\n\tconst types = (body as { workItemTypeMappedStates?: unknown } | null)?.workItemTypeMappedStates;\n\tif (!Array.isArray(types)) throw new Error('Azure DevOps returned no workflow category mappings');\n\n\tconst result = new Map<string, Map<string, string>>();\n\tfor (const type of types as { workItemTypeName?: unknown; states?: unknown }[]) {\n\t\tif (\n\t\t\ttypeof type?.workItemTypeName !== 'string' ||\n\t\t\t!type.workItemTypeName.trim() ||\n\t\t\ttype.states == null ||\n\t\t\ttypeof type.states !== 'object' ||\n\t\t\tArray.isArray(type.states)\n\t\t) {\n\t\t\tthrow new Error('Azure DevOps returned invalid workflow category mappings');\n\t\t}\n\n\t\tconst states = result.get(type.workItemTypeName) ?? new Map<string, string>();\n\t\tfor (const [name, category] of Object.entries(type.states)) {\n\t\t\tif (\n\t\t\t\t!name.trim() ||\n\t\t\t\ttypeof category !== 'string' ||\n\t\t\t\tazureIssueStateCategory(category as AzureWorkItemStateCategory) == null ||\n\t\t\t\t(states.has(name) && states.get(name) !== category)\n\t\t\t) {\n\t\t\t\tthrow new Error('Azure DevOps returned invalid workflow category mappings');\n\t\t\t}\n\n\t\t\tstates.set(name, category);\n\t\t}\n\t\tresult.set(type.workItemTypeName, states);\n\t}\n\treturn result;\n}\n\nfunction scopeKey(scope: AzureWorkItemStatesScope, type?: string): string {\n\tencodeAzurePathSegment(scope.namespace);\n\tencodeAzurePathSegment(scope.project);\n\tif (type != null) {\n\t\tencodeAzurePathSegment(type);\n\t}\n\n\treturn JSON.stringify([\n\t\tscope.baseUrl.replace(/\\/$/, ''),\n\t\tscope.namespace.toLowerCase(),\n\t\tscope.project.toLowerCase(),\n\t\ttype?.toLowerCase(),\n\t\tscope.token,\n\t\tscope.isPAT,\n\t]);\n}\n\n/**\n * Workflow metadata per project, work item type and token, kept for 5 minutes. A failed read is kept for 30 seconds,\n * so the pages and per-type reads of a listing fail fast with the same error instead of each asking a failing server\n * again; the first read after that retries.\n */\nexport class AzureWorkItemStatesCache {\n\tprivate readonly types = new PromiseCache<string, PromiseSettledResult<string[]>>({\n\t\tcreateTTL: 5 * 60 * 1000,\n\t\tcapacity: 256,\n\t});\n\tprivate readonly states = new PromiseCache<string, PromiseSettledResult<WorkItemTypeStatesSnapshot>>({\n\t\tcreateTTL: 5 * 60 * 1000,\n\t\tcapacity: 256,\n\t});\n\n\tprivate readonly mappings = new PromiseCache<string, PromiseSettledResult<WorkItemStateMappings>>({\n\t\tcreateTTL: 5 * 60 * 1000,\n\t\tcapacity: 256,\n\t});\n\n\tclear(): void {\n\t\tthis.types.clear();\n\t\tthis.states.clear();\n\t\tthis.mappings.clear();\n\t}\n\n\tgetTypes(\n\t\tscope: AzureWorkItemStatesScope,\n\t\tread: (signal?: AbortSignal) => Promise<unknown>,\n\t\tcancellation?: AbortSignal,\n\t): Promise<string[]> {\n\t\treturn this.read(\n\t\t\tthis.types,\n\t\t\tscopeKey(scope),\n\t\t\tasync signal => parseWorkItemTypes(await read(signal)),\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\tgetStates(\n\t\tscope: AzureWorkItemStatesScope,\n\t\ttype: string,\n\t\tread: (signal?: AbortSignal) => Promise<unknown>,\n\t\tcancellation?: AbortSignal,\n\t\treadMappings?: (signal?: AbortSignal) => Promise<unknown>,\n\t): Promise<WorkItemTypeStatesSnapshot> {\n\t\treturn this.read(\n\t\t\tthis.states,\n\t\t\tscopeKey(scope, type),\n\t\t\tasync signal => {\n\t\t\t\tconst states = parseWorkItemStates(await read(signal), readMappings != null);\n\t\t\t\tif (readMappings == null || states.every(state => state.category != null)) {\n\t\t\t\t\treturn { states: states, usesLegacyMappings: false };\n\t\t\t\t}\n\n\t\t\t\tconst mappings = await this.read(\n\t\t\t\t\tthis.mappings,\n\t\t\t\t\tscopeKey(scope),\n\t\t\t\t\tasync aggregate => parseWorkItemStateMappings(await readMappings(aggregate)),\n\t\t\t\t\tsignal,\n\t\t\t\t);\n\t\t\t\tconst mapped = mappings.get(type);\n\t\t\t\treturn {\n\t\t\t\t\tstates: states.map(state => ({\n\t\t\t\t\t\tname: state.name,\n\t\t\t\t\t\tcategory: state.category ?? mapped?.get(state.name),\n\t\t\t\t\t})),\n\t\t\t\t\tusesLegacyMappings: true,\n\t\t\t\t};\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\tprivate async read<T>(\n\t\tcache: PromiseCache<string, PromiseSettledResult<T>>,\n\t\tkey: string,\n\t\tload: (signal?: AbortSignal) => Promise<T>,\n\t\tcancellation?: AbortSignal,\n\t): Promise<T> {\n\t\tconst result = await cache.getOrCreate(\n\t\t\tkey,\n\t\t\tasync (_cacheable, signal) => ({ status: 'fulfilled', value: await load(signal) }),\n\t\t\t{\n\t\t\t\tcancellation: cancellation,\n\t\t\t\t// Every caller must still see the failure; caching undefined would turn later pages into successes.\n\t\t\t\tonError: error =>\n\t\t\t\t\tisCancellationError(error) || cache.get(key) == null\n\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t: { value: { status: 'rejected', reason: error }, createTTL: 30 * 1000, suppress: true },\n\t\t\t},\n\t\t);\n\t\tif (result.status === 'rejected') throw result.reason;\n\n\t\treturn result.value;\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"workItemStateCategories.js","names":[],"sources":["../../../../../../plus/integrations/src/providers/azure/workItemStateCategories.ts"],"sourcesContent":["import type { AzureWorkItemTypeStates } from '@gitkraken/provider-apis';\nimport { isCancellationError } from '@gitlens/utils/cancellation.js';\nimport { PromiseCache } from '@gitlens/utils/promiseCache.js';\nimport type { AzureWorkItemStateCategory } from './models.js';\nimport { azureIssueStateCategory, encodeAzurePathSegment } from './models.js';\n\ntype WorkItemTypeStates = readonly { name: string; category?: string }[];\ntype WorkItemTypeStatesSnapshot = {\n\tstates: WorkItemTypeStates;\n\tusesLegacyMappings: boolean;\n};\ntype WorkItemStateMappings = ReadonlyMap<string, ReadonlyMap<string, string>>;\n\nexport type AzureWorkItemStatesScope = {\n\tbaseUrl: string;\n\tnamespace: string;\n\tproject: string;\n\ttoken: string;\n\tisPAT: boolean;\n};\n\n// Older servers return a 404 page for unsupported API versions, so callers must supply the negotiated version.\nexport function getAzureWorkItemTypesUrl(\n\tbaseUrl: string,\n\tnamespace: string,\n\tproject: string,\n\tapiVersion: string,\n): string {\n\treturn `${baseUrl.replace(/\\/$/, '')}/${encodeAzurePathSegment(namespace)}/${encodeAzurePathSegment(project)}/_apis/wit/workItemTypes?api-version=${apiVersion}`;\n}\n\n// Azure DevOps Server serves this endpoint only as a preview.\nexport function getAzureWorkItemTypeStatesPath(\n\tnamespace: string,\n\tproject: string,\n\ttype: string,\n\tapiVersion: string,\n): string {\n\treturn `${encodeAzurePathSegment(namespace)}/${encodeAzurePathSegment(project)}/_apis/wit/workItemTypes/${encodeAzurePathSegment(type)}/states?api-version=${apiVersion}`;\n}\n\nexport function getAzureWorkItemTypeStatesUrl(\n\tbaseUrl: string,\n\tnamespace: string,\n\tproject: string,\n\ttype: string,\n\tapiVersion: string,\n): string {\n\treturn `${baseUrl.replace(/\\/$/, '')}/${getAzureWorkItemTypeStatesPath(namespace, project, type, apiVersion)}`;\n}\n\nfunction parseWorkItemTypes(body: unknown): string[] {\n\tconst types = (body as { value?: unknown } | null)?.value;\n\tif (!Array.isArray(types)) throw new Error('Azure DevOps returned no work item types');\n\n\tconst names: string[] = [];\n\tfor (const type of types as { name?: unknown }[]) {\n\t\tif (typeof type?.name !== 'string' || !type.name.trim()) {\n\t\t\tthrow new Error('Azure DevOps returned an invalid work item type');\n\t\t}\n\n\t\tnames.push(type.name);\n\t}\n\treturn [...new Set(names)];\n}\n\nfunction parseWorkItemStates(body: unknown, allowMissingCategory = false): WorkItemTypeStates {\n\tconst states = (body as { value?: unknown } | null)?.value;\n\tif (!Array.isArray(states) || states.length === 0) throw new Error('Azure DevOps returned no work item states');\n\n\tconst parsed: { name: string; category?: string }[] = [];\n\tfor (const state of states as { name?: unknown; category?: unknown }[]) {\n\t\tif (\n\t\t\ttypeof state?.name !== 'string' ||\n\t\t\t!state.name.trim() ||\n\t\t\t(state.category === undefined\n\t\t\t\t? !allowMissingCategory\n\t\t\t\t: typeof state.category !== 'string' ||\n\t\t\t\t\tazureIssueStateCategory(state.category as AzureWorkItemStateCategory) == null) ||\n\t\t\tparsed.some(s => s.name === state.name && s.category !== state.category)\n\t\t) {\n\t\t\tthrow new Error('Azure DevOps returned an invalid work item state');\n\t\t}\n\n\t\tparsed.push({ name: state.name, category: state.category as string | undefined });\n\t}\n\treturn parsed;\n}\n\nexport function resolveAzureWorkItemStateCategory(\n\tsnapshot: WorkItemTypeStatesSnapshot,\n\tstate: string,\n): AzureWorkItemStateCategory | undefined {\n\tconst matched = snapshot.states.find(s => s.name === state);\n\tconst category = matched?.category as AzureWorkItemStateCategory | undefined;\n\tif ((snapshot.usesLegacyMappings || matched != null) && category == null) {\n\t\tthrow new Error(`Azure DevOps does not expose a category for work item state '${state}'`);\n\t}\n\n\treturn category;\n}\n\nexport function requireAzureWorkItemStateCategories(\n\tsnapshot: WorkItemTypeStatesSnapshot,\n): NonNullable<AzureWorkItemTypeStates['types'][number]['states']> {\n\treturn snapshot.states.map(state => {\n\t\tif (state.category == null) throw new Error('Azure DevOps does not expose a category for this work item state');\n\n\t\treturn { name: state.name, category: state.category };\n\t});\n}\n\nfunction parseWorkItemStateMappings(body: unknown): WorkItemStateMappings {\n\tconst types = (body as { workItemTypeMappedStates?: unknown } | null)?.workItemTypeMappedStates;\n\tif (!Array.isArray(types)) throw new Error('Azure DevOps returned no workflow category mappings');\n\n\tconst result = new Map<string, Map<string, string>>();\n\tfor (const type of types as { workItemTypeName?: unknown; states?: unknown }[]) {\n\t\tif (\n\t\t\ttypeof type?.workItemTypeName !== 'string' ||\n\t\t\t!type.workItemTypeName.trim() ||\n\t\t\ttype.states == null ||\n\t\t\ttypeof type.states !== 'object' ||\n\t\t\tArray.isArray(type.states)\n\t\t) {\n\t\t\tthrow new Error('Azure DevOps returned invalid workflow category mappings');\n\t\t}\n\n\t\tconst states = result.get(type.workItemTypeName) ?? new Map<string, string>();\n\t\tfor (const [name, category] of Object.entries(type.states)) {\n\t\t\tif (\n\t\t\t\t!name.trim() ||\n\t\t\t\ttypeof category !== 'string' ||\n\t\t\t\tazureIssueStateCategory(category as AzureWorkItemStateCategory) == null ||\n\t\t\t\t(states.has(name) && states.get(name) !== category)\n\t\t\t) {\n\t\t\t\tthrow new Error('Azure DevOps returned invalid workflow category mappings');\n\t\t\t}\n\n\t\t\tstates.set(name, category);\n\t\t}\n\t\tresult.set(type.workItemTypeName, states);\n\t}\n\treturn result;\n}\n\nfunction scopeKey(scope: AzureWorkItemStatesScope, type?: string): string {\n\tencodeAzurePathSegment(scope.namespace);\n\tencodeAzurePathSegment(scope.project);\n\tif (type != null) {\n\t\tencodeAzurePathSegment(type);\n\t}\n\n\treturn JSON.stringify([\n\t\tscope.baseUrl.replace(/\\/$/, ''),\n\t\tscope.namespace.toLowerCase(),\n\t\tscope.project.toLowerCase(),\n\t\ttype?.toLowerCase(),\n\t\tscope.token,\n\t\tscope.isPAT,\n\t]);\n}\n\n/**\n * Workflow metadata per project, work item type and token, kept for 5 minutes. A failed read is kept for 30 seconds,\n * so the pages and per-type reads of a listing fail fast with the same error instead of each asking a failing server\n * again; the first read after that retries.\n */\nexport class AzureWorkItemStatesCache {\n\tprivate readonly types = new PromiseCache<string, PromiseSettledResult<string[]>>({\n\t\tcreateTTL: 5 * 60 * 1000,\n\t\tcapacity: 256,\n\t});\n\tprivate readonly states = new PromiseCache<string, PromiseSettledResult<WorkItemTypeStatesSnapshot>>({\n\t\tcreateTTL: 5 * 60 * 1000,\n\t\tcapacity: 256,\n\t});\n\n\tprivate readonly mappings = new PromiseCache<string, PromiseSettledResult<WorkItemStateMappings>>({\n\t\tcreateTTL: 5 * 60 * 1000,\n\t\tcapacity: 256,\n\t});\n\n\tclear(): void {\n\t\tthis.types.clear();\n\t\tthis.states.clear();\n\t\tthis.mappings.clear();\n\t}\n\n\tgetTypes(\n\t\tscope: AzureWorkItemStatesScope,\n\t\tread: (signal?: AbortSignal) => Promise<unknown>,\n\t\tcancellation?: AbortSignal,\n\t): Promise<string[]> {\n\t\treturn this.read(\n\t\t\tthis.types,\n\t\t\tscopeKey(scope),\n\t\t\tasync signal => parseWorkItemTypes(await read(signal)),\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\tgetStates(\n\t\tscope: AzureWorkItemStatesScope,\n\t\ttype: string,\n\t\tread: (signal?: AbortSignal) => Promise<unknown>,\n\t\tcancellation?: AbortSignal,\n\t\treadMappings?: (signal?: AbortSignal) => Promise<unknown>,\n\t): Promise<WorkItemTypeStatesSnapshot> {\n\t\treturn this.read(\n\t\t\tthis.states,\n\t\t\tscopeKey(scope, type),\n\t\t\tasync signal => {\n\t\t\t\tconst states = parseWorkItemStates(await read(signal), readMappings != null);\n\t\t\t\tif (readMappings == null || states.every(state => state.category != null)) {\n\t\t\t\t\treturn { states: states, usesLegacyMappings: false };\n\t\t\t\t}\n\n\t\t\t\tconst mappings = await this.read(\n\t\t\t\t\tthis.mappings,\n\t\t\t\t\tscopeKey(scope),\n\t\t\t\t\tasync aggregate => parseWorkItemStateMappings(await readMappings(aggregate)),\n\t\t\t\t\tsignal,\n\t\t\t\t);\n\t\t\t\tconst mapped = mappings.get(type);\n\t\t\t\treturn {\n\t\t\t\t\tstates: states.map(state => ({\n\t\t\t\t\t\tname: state.name,\n\t\t\t\t\t\tcategory: state.category ?? mapped?.get(state.name),\n\t\t\t\t\t})),\n\t\t\t\t\tusesLegacyMappings: true,\n\t\t\t\t};\n\t\t\t},\n\t\t\tcancellation,\n\t\t);\n\t}\n\n\tprivate async read<T>(\n\t\tcache: PromiseCache<string, PromiseSettledResult<T>>,\n\t\tkey: string,\n\t\tload: (signal?: AbortSignal) => Promise<T>,\n\t\tcancellation?: AbortSignal,\n\t): Promise<T> {\n\t\tconst result = await cache.getOrCreate(\n\t\t\tkey,\n\t\t\tasync (_cacheable, signal) => ({ status: 'fulfilled', value: await load(signal) }),\n\t\t\t{\n\t\t\t\tcancellation: cancellation,\n\t\t\t\t// Every caller must still see the failure; caching undefined would turn later pages into successes.\n\t\t\t\tonError: error =>\n\t\t\t\t\tisCancellationError(error) || cache.get(key) == null\n\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t: { value: { status: 'rejected', reason: error }, createTTL: 30 * 1000, suppress: true },\n\t\t\t},\n\t\t);\n\t\tif (result.status === 'rejected') throw result.reason;\n\n\t\treturn result.value;\n\t}\n}\n"],"mappings":";;;;AAsBA,SAAgB,yBACf,SACA,WACA,SACA,YACS;CACT,OAAO,GAAG,QAAQ,QAAQ,OAAO,EAAE,EAAE,GAAG,uBAAuB,SAAS,EAAE,GAAG,uBAAuB,OAAO,EAAE,uCAAuC;AACrJ;AAGA,SAAgB,+BACf,WACA,SACA,MACA,YACS;CACT,OAAO,GAAG,uBAAuB,SAAS,EAAE,GAAG,uBAAuB,OAAO,EAAE,2BAA2B,uBAAuB,IAAI,EAAE,sBAAsB;AAC9J;AAEA,SAAgB,8BACf,SACA,WACA,SACA,MACA,YACS;CACT,OAAO,GAAG,QAAQ,QAAQ,OAAO,EAAE,EAAE,GAAG,+BAA+B,WAAW,SAAS,MAAM,UAAU;AAC5G;AAEA,SAAS,mBAAmB,MAAyB;CACpD,MAAM,QAAS,MAAqC;CACpD,IAAI,CAAC,MAAM,QAAQ,KAAK,GAAG,MAAM,IAAI,MAAM,0CAA0C;CAErF,MAAM,QAAkB,CAAC;CACzB,KAAK,MAAM,QAAQ,OAA+B;EACjD,IAAI,OAAO,MAAM,SAAS,YAAY,CAAC,KAAK,KAAK,KAAK,GACrD,MAAM,IAAI,MAAM,iDAAiD;EAGlE,MAAM,KAAK,KAAK,IAAI;CACrB;CACA,OAAO,CAAC,GAAG,IAAI,IAAI,KAAK,CAAC;AAC1B;AAEA,SAAS,oBAAoB,MAAe,uBAAuB,OAA2B;CAC7F,MAAM,SAAU,MAAqC;CACrD,IAAI,CAAC,MAAM,QAAQ,MAAM,KAAK,OAAO,WAAW,GAAG,MAAM,IAAI,MAAM,2CAA2C;CAE9G,MAAM,SAAgD,CAAC;CACvD,KAAK,MAAM,SAAS,QAAoD;EACvE,IACC,OAAO,OAAO,SAAS,YACvB,CAAC,MAAM,KAAK,KAAK,MAChB,MAAM,aAAa,KAAA,IACjB,CAAC,uBACD,OAAO,MAAM,aAAa,YAC3B,wBAAwB,MAAM,QAAsC,KAAK,SAC3E,OAAO,MAAK,MAAK,EAAE,SAAS,MAAM,QAAQ,EAAE,aAAa,MAAM,QAAQ,GAEvE,MAAM,IAAI,MAAM,kDAAkD;EAGnE,OAAO,KAAK;GAAE,MAAM,MAAM;GAAM,UAAU,MAAM;EAA+B,CAAC;CACjF;CACA,OAAO;AACR;AAEA,SAAgB,kCACf,UACA,OACyC;CACzC,MAAM,UAAU,SAAS,OAAO,MAAK,MAAK,EAAE,SAAS,KAAK;CAC1D,MAAM,WAAW,SAAS;CAC1B,KAAK,SAAS,sBAAsB,WAAW,SAAS,YAAY,MACnE,MAAM,IAAI,MAAM,gEAAgE,MAAM,EAAE;CAGzF,OAAO;AACR;AAEA,SAAgB,oCACf,UACkE;CAClE,OAAO,SAAS,OAAO,KAAI,UAAS;EACnC,IAAI,MAAM,YAAY,MAAM,MAAM,IAAI,MAAM,kEAAkE;EAE9G,OAAO;GAAE,MAAM,MAAM;GAAM,UAAU,MAAM;EAAS;CACrD,CAAC;AACF;AAEA,SAAS,2BAA2B,MAAsC;CACzE,MAAM,QAAS,MAAwD;CACvE,IAAI,CAAC,MAAM,QAAQ,KAAK,GAAG,MAAM,IAAI,MAAM,qDAAqD;CAEhG,MAAM,yBAAS,IAAI,IAAiC;CACpD,KAAK,MAAM,QAAQ,OAA6D;EAC/E,IACC,OAAO,MAAM,qBAAqB,YAClC,CAAC,KAAK,iBAAiB,KAAK,KAC5B,KAAK,UAAU,QACf,OAAO,KAAK,WAAW,YACvB,MAAM,QAAQ,KAAK,MAAM,GAEzB,MAAM,IAAI,MAAM,0DAA0D;EAG3E,MAAM,SAAS,OAAO,IAAI,KAAK,gBAAgB,qBAAK,IAAI,IAAoB;EAC5E,KAAK,MAAM,CAAC,MAAM,aAAa,OAAO,QAAQ,KAAK,MAAM,GAAG;GAC3D,IACC,CAAC,KAAK,KAAK,KACX,OAAO,aAAa,YACpB,wBAAwB,QAAsC,KAAK,QAClE,OAAO,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI,MAAM,UAE1C,MAAM,IAAI,MAAM,0DAA0D;GAG3E,OAAO,IAAI,MAAM,QAAQ;EAC1B;EACA,OAAO,IAAI,KAAK,kBAAkB,MAAM;CACzC;CACA,OAAO;AACR;AAEA,SAAS,SAAS,OAAiC,MAAuB;CACzE,uBAAuB,MAAM,SAAS;CACtC,uBAAuB,MAAM,OAAO;CACpC,IAAI,QAAQ,MACX,uBAAuB,IAAI;CAG5B,OAAO,KAAK,UAAU;EACrB,MAAM,QAAQ,QAAQ,OAAO,EAAE;EAC/B,MAAM,UAAU,YAAY;EAC5B,MAAM,QAAQ,YAAY;EAC1B,MAAM,YAAY;EAClB,MAAM;EACN,MAAM;CACP,CAAC;AACF;;;;;;AAOA,IAAa,2BAAb,MAAsC;CACrC,QAAyB,IAAI,aAAqD;EACjF,WAAW;EACX,UAAU;CACX,CAAC;CACD,SAA0B,IAAI,aAAuE;EACpG,WAAW;EACX,UAAU;CACX,CAAC;CAED,WAA4B,IAAI,aAAkE;EACjG,WAAW;EACX,UAAU;CACX,CAAC;CAED,QAAc;EACb,KAAK,MAAM,MAAM;EACjB,KAAK,OAAO,MAAM;EAClB,KAAK,SAAS,MAAM;CACrB;CAEA,SACC,OACA,MACA,cACoB;EACpB,OAAO,KAAK,KACX,KAAK,OACL,SAAS,KAAK,GACd,OAAM,WAAU,mBAAmB,MAAM,KAAK,MAAM,CAAC,GACrD,YACD;CACD;CAEA,UACC,OACA,MACA,MACA,cACA,cACsC;EACtC,OAAO,KAAK,KACX,KAAK,QACL,SAAS,OAAO,IAAI,GACpB,OAAM,WAAU;GACf,MAAM,SAAS,oBAAoB,MAAM,KAAK,MAAM,GAAG,gBAAgB,IAAI;GAC3E,IAAI,gBAAgB,QAAQ,OAAO,OAAM,UAAS,MAAM,YAAY,IAAI,GACvE,OAAO;IAAU;IAAQ,oBAAoB;GAAM;GASpD,MAAM,UAAS,MANQ,KAAK,KAC3B,KAAK,UACL,SAAS,KAAK,GACd,OAAM,cAAa,2BAA2B,MAAM,aAAa,SAAS,CAAC,GAC3E,MACD,EAAA,CACwB,IAAI,IAAI;GAChC,OAAO;IACN,QAAQ,OAAO,KAAI,WAAU;KAC5B,MAAM,MAAM;KACZ,UAAU,MAAM,YAAY,QAAQ,IAAI,MAAM,IAAI;IACnD,EAAE;IACF,oBAAoB;GACrB;EACD,GACA,YACD;CACD;CAEA,MAAc,KACb,OACA,KACA,MACA,cACa;EACb,MAAM,SAAS,MAAM,MAAM,YAC1B,KACA,OAAO,YAAY,YAAY;GAAE,QAAQ;GAAa,OAAO,MAAM,KAAK,MAAM;EAAE,IAChF;GACe;GAEd,UAAS,UACR,oBAAoB,KAAK,KAAK,MAAM,IAAI,GAAG,KAAK,OAC7C,KAAA,IACA;IAAE,OAAO;KAAE,QAAQ;KAAY,QAAQ;IAAM;IAAG,WAAW;IAAW,UAAU;GAAK;EAC1F,CACD;EACA,IAAI,OAAO,WAAW,YAAY,MAAM,OAAO;EAE/C,OAAO,OAAO;CACf;AACD"}
@@ -1,5 +1,4 @@
1
1
  import { IssueSorting } from "../../../git/models/issue.js";
2
- import "../providerFilters.js";
3
2
  //#region ../plus/integrations/src/providers/issueSorts.d.ts
4
3
  /** GitHub and GHE: one `search` channel serves all three issue reads, so all three order the same way. */
5
4
  export declare const githubIssueSorts: IssueSorting[];
@@ -1,6 +1,6 @@
1
1
  import { equalsIgnoreCase } from "../../../utils/string.js";
2
2
  import { gitSuffixRegex } from "../../../git/utils/remote.utils.js";
3
- import { Issue } from "../../../git/models/issue.js";
3
+ import { Issue as Issue$1 } from "../../../git/models/issue.js";
4
4
  import { PullRequest, PullRequestFilter } from "../../../git/models/pullRequest.js";
5
5
  import { isTerminalIssueStateCategory } from "../../../git/utils/issue.utils.js";
6
6
  import "../constants.js";
@@ -12,8 +12,7 @@ import { azurePullRequestSearchSorts, azureWorkItemSearchRelationships, azureWor
12
12
  import { azureAccountWideIssueSorts, azureIssueSorts, githubAccountWideIssueSorts, githubIssueSorts, gitlabAccountWideIssueSorts, gitlabIssueSorts, jiraIssueSorts, linearIssueSorts, trelloIssueSorts } from "./issueSorts.js";
13
13
  import { fromPullRequestReviewDecision, toCompletedReviews, toProviderReviewDecision, toProviderReviews, toReviewRequests } from "./pullRequestReviews.js";
14
14
  import { getEntityIdentifierInput } from "./utils.js";
15
- import { EntityIdentifierUtils } from "@gitkraken/provider-apis/entity-identifiers";
16
- import { GitProviderUtils } from "@gitkraken/provider-apis/provider-utils";
15
+ import { EntityIdentifierUtils, GitProviderUtils } from "@gitkraken/provider-apis";
17
16
  //#region ../plus/integrations/src/providers/models.ts
18
17
  const GitBuildStatusState = {
19
18
  ActionRequired: "ACTION_REQUIRED",
@@ -626,12 +625,7 @@ function toIssueShape(issue, provider, options) {
626
625
  avatarUrl: assignee.avatarUrl ?? void 0,
627
626
  url: assignee.url ?? void 0
628
627
  })) ?? [],
629
- project: issue.project?.id && issue.project.resourceId && issue.project.namespace ? {
630
- id: issue.project.id,
631
- name: issue.project.name,
632
- resourceId: issue.project.resourceId,
633
- resourceName: issue.project.namespace
634
- } : void 0,
628
+ project: toIssueProject(issue.project, provider),
635
629
  repository: issue.repository?.owner?.login != null ? {
636
630
  owner: issue.repository.owner.login,
637
631
  repo: issue.repository.name,
@@ -652,6 +646,15 @@ function toIssueShape(issue, provider, options) {
652
646
  ...toIssueViewer(issue, options?.viewer)
653
647
  };
654
648
  }
649
+ function toIssueProject(project, provider) {
650
+ if (!project?.id || !project.resourceId || !project.namespace && !isJiraIntegrationId(provider.id)) return;
651
+ return {
652
+ id: project.id,
653
+ name: project.name,
654
+ resourceId: project.resourceId,
655
+ resourceName: project.namespace ?? ""
656
+ };
657
+ }
655
658
  function toIssueBodyField(field) {
656
659
  return {
657
660
  id: field.referenceName,
@@ -1016,7 +1019,7 @@ function fromProviderIssue(issue, integration, options) {
1016
1019
  const identifier = toIssueIdentifier(issue.number);
1017
1020
  const state = getProviderIssueState(issue, integration.id);
1018
1021
  const viewer = toIssueViewer(issue, options?.viewer);
1019
- return new Issue(integration, identifier, issue.graphQLId ?? issue.id, issue.title, issue.url ?? "", issue.createdDate, issue.updatedDate ?? issue.closedDate ?? issue.createdDate, state === "closed", state, fromProviderAccount(issue.author), issue.assignees?.map(fromProviderAccount) ?? void 0, issue.repository != null ? {
1022
+ return new Issue$1(integration, identifier, issue.graphQLId ?? issue.id, issue.title, issue.url ?? "", issue.createdDate, issue.updatedDate ?? issue.closedDate ?? issue.createdDate, state === "closed", state, fromProviderAccount(issue.author), issue.assignees?.map(fromProviderAccount) ?? void 0, issue.repository != null ? {
1020
1023
  owner: issue.repository.owner.login ?? "",
1021
1024
  repo: issue.repository.name,
1022
1025
  id: issue.repository.id || void 0
@@ -1028,12 +1031,7 @@ function fromProviderIssue(issue, integration, options) {
1028
1031
  name: options.project.name,
1029
1032
  resourceId: options.project.resourceId,
1030
1033
  resourceName: options.project.resourceName
1031
- } : issue.project?.id && issue.project?.resourceId && issue.project?.namespace ? {
1032
- id: issue.project.id,
1033
- name: issue.project.name,
1034
- resourceId: issue.project.resourceId,
1035
- resourceName: issue.project.namespace
1036
- } : void 0, identifier, issue.type ?? void 0, toIssueProviderState(issue.state), integration.id === "jira" ? "jira-wiki" : void 0, toIssueIterations(issue), options?.projection, issue.descriptionField != null ? toIssueBodyField(issue.descriptionField) : void 0, viewer?.viewer, viewer?.viewerUnresolved);
1034
+ } : toIssueProject(issue.project, integration), identifier, issue.type ?? void 0, toIssueProviderState(issue.state), integration.id === "jira" ? "jira-wiki" : void 0, toIssueIterations(issue), options?.projection, issue.descriptionField != null ? toIssueBodyField(issue.descriptionField) : void 0, viewer?.viewer, viewer?.viewerUnresolved);
1037
1035
  }
1038
1036
  function toProviderPullRequestWithUniqueId(pr) {
1039
1037
  const { reviews, mergeableState, ...providerPr } = toProviderPullRequest(pr);