import { ConnectConfig } from 'ssh2'; export interface ProxyConfig { type: 'socks4' | 'socks5' | 'http'; host: string; port: number; } export type ConfigLocation = number | string; export function formatConfigLocation(location?: ConfigLocation): string { if (!location) return 'Unknown location'; if (typeof location === 'number') { return `${[, 'Global', 'Workspace', 'WorkspaceFolder'][location] || 'Unknown'} settings.json`; } return location; } export function getLocations(configs: FileSystemConfig[]): ConfigLocation[] { const res: ConfigLocation[] = [1, 2 /*, 3*/]; // No WorkspaceFolder support (for now) // TODO: Suggest creating sshfs.jsonc etc in current workspace folder(s) (UI feature?) for (const { _location } of configs) { if (!_location) continue; if (!res.find(l => l === _location)) { res.push(_location); } } return res; } export function groupByLocation(configs: FileSystemConfig[]): [ConfigLocation, FileSystemConfig[]][] { const res: [ConfigLocation, FileSystemConfig[]][] = []; function getForLoc(loc: ConfigLocation = 'Unknown') { let found = res.find(([l]) => l === loc); if (found) return found; found = [loc, []]; res.push(found); return found; } for (const config of configs) { getForLoc(config._location!)[1].push(config); } return res; } export interface FileSystemConfig extends ConnectConfig { /* Name of the config. Can only exists of lowercase alphanumeric characters, slashes and any of these: _.+-@ */ name: string; /* Optional label to display in some UI places (e.g. popups) */ label?: string; /* Whether to merge this "lower" config (e.g. from workspace settings) into higher configs (e.g. from global settings) */ merge?: boolean; /* Path on the remote server where the root path in vscode should point to. Defaults to / */ root?: string; /* A name of a PuTTY session, or `true` to find the PuTTY session from the host address */ putty?: string | boolean; /* Optional object defining a proxy to use */ proxy?: ProxyConfig; /* Optional path to a private keyfile to authenticate with */ privateKeyPath?: string; /* A name of another config to use as a hop */ hop?: string; /* A command to run on the remote SSH session to start a SFTP session (defaults to sftp subsystem) */ sftpCommand?: string; /* Whether to use a sudo shell (and for which user) to run the sftpCommand in (sftpCommand defaults to /usr/lib/openssh/sftp-server if missing) */ sftpSudo?: string | boolean; /* The filemode to assign to created files */ newFileMode?: number | string; /* Internal property saying where this config comes from. Undefined if this config is merged or something */ _location?: ConfigLocation; /* Internal property keeping track of where this config comes from (including merges) */ _locations: ConfigLocation[]; } export function invalidConfigName(name: string) { if (!name) return 'Missing a name for this SSH FS'; if (name.match(/^[\w_\\\/\.@\-+]+$/)) return null; return `A SSH FS name can only exists of lowercase alphanumeric characters, slashes and any of these: _.+-@`; }