MCPcopy Create free account
hub / github.com/bytebase/dbhub / resolveJumpHosts

Function resolveJumpHosts

src/utils/ssh-config-parser.ts:365–415  ·  view source on GitHub ↗
(
  proxyJump: string,
  configPath: string,
  visited: Set<string> = new Set()
)

Source from the content-addressed store, hash-verified

363 * @param visited Aliases already on the current resolution path (cycle guard)
364 */
365export function resolveJumpHosts(
366 proxyJump: string,
367 configPath: string,
368 visited: Set<string> = new Set()
369): JumpHost[] {
370 if (!proxyJump || proxyJump.trim() === '' || proxyJump.toLowerCase() === 'none') {
371 return [];
372 }
373
374 const resolved: JumpHost[] = [];
375
376 // Iterate the raw tokens (not parseJumpHosts output) so we can tell an explicit
377 // `:port` from the normalized default of 22 — needed to let a token port override
378 // a config alias's Port.
379 for (const token of proxyJump.split(',').map((s) => s.trim()).filter((s) => s.length > 0)) {
380 const hop = parseJumpHost(token);
381
382 if (!looksLikeSSHAlias(hop.host)) {
383 resolved.push(hop); // literal host — nothing to resolve
384 continue;
385 }
386
387 if (visited.has(hop.host)) {
388 throw new Error(`Cycle detected in SSH ProxyJump chain at alias "${hop.host}"`);
389 }
390
391 // Jump-host aliases may omit `User` (inherited from the target), so don't require it.
392 const aliasConfig = parseSSHConfig(hop.host, configPath, { requireUser: false });
393 if (!aliasConfig) {
394 resolved.push(hop); // alias not in config — treat the token literally
395 continue;
396 }
397
398 // Expand this alias's own jump chain first so it connects before the alias.
399 if (aliasConfig.proxyJump) {
400 resolved.push(...resolveJumpHosts(aliasConfig.proxyJump, configPath, new Set(visited).add(hop.host)));
401 }
402
403 resolved.push({
404 host: aliasConfig.host,
405 // An explicit `:port` on the token wins; otherwise use the alias's Port (default 22).
406 port: tokenHasExplicitPort(token) ? hop.port : aliasConfig.port ?? 22,
407 // An explicit `user@` on the token wins; otherwise the alias's User.
408 username: hop.username ?? aliasConfig.username,
409 privateKey: aliasConfig.privateKey,
410 passphrase: aliasConfig.passphrase,
411 });
412 }
413
414 return resolved;
415}
416
417/**
418 * Whether a ProxyJump token carries an explicit `:port` (vs. relying on the

Callers 2

connectSourceMethod · 0.85

Calls 5

parseJumpHostFunction · 0.85
looksLikeSSHAliasFunction · 0.85
parseSSHConfigFunction · 0.85
tokenHasExplicitPortFunction · 0.85
addMethod · 0.80

Tested by

no test coverage detected