@lemoncat7/dsh-ssh 0.1.0-alpha.15

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.
Files changed (76) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +105 -0
  3. package/cordis.patch.yml +10 -0
  4. package/lib/api.d.ts +23 -0
  5. package/lib/api.d.ts.map +1 -0
  6. package/lib/api.js +571 -0
  7. package/lib/api.js.map +1 -0
  8. package/lib/client-api.d.ts +174 -0
  9. package/lib/client-api.d.ts.map +1 -0
  10. package/lib/client-api.js +88 -0
  11. package/lib/client-api.js.map +1 -0
  12. package/lib/client.d.ts +4 -0
  13. package/lib/client.d.ts.map +1 -0
  14. package/lib/client.js +8067 -0
  15. package/lib/client.js.map +7 -0
  16. package/lib/config.d.ts +14 -0
  17. package/lib/config.d.ts.map +1 -0
  18. package/lib/config.js +31 -0
  19. package/lib/config.js.map +1 -0
  20. package/lib/connector.d.ts +30 -0
  21. package/lib/connector.d.ts.map +1 -0
  22. package/lib/connector.js +216 -0
  23. package/lib/connector.js.map +1 -0
  24. package/lib/credentials.d.ts +25 -0
  25. package/lib/credentials.d.ts.map +1 -0
  26. package/lib/credentials.js +84 -0
  27. package/lib/credentials.js.map +1 -0
  28. package/lib/directory.d.ts +8 -0
  29. package/lib/directory.d.ts.map +1 -0
  30. package/lib/directory.js +45 -0
  31. package/lib/directory.js.map +1 -0
  32. package/lib/domain.d.ts +121 -0
  33. package/lib/domain.d.ts.map +1 -0
  34. package/lib/domain.js +136 -0
  35. package/lib/domain.js.map +1 -0
  36. package/lib/exec.d.ts +15 -0
  37. package/lib/exec.d.ts.map +1 -0
  38. package/lib/exec.js +82 -0
  39. package/lib/exec.js.map +1 -0
  40. package/lib/forwards.d.ts +26 -0
  41. package/lib/forwards.d.ts.map +1 -0
  42. package/lib/forwards.js +213 -0
  43. package/lib/forwards.js.map +1 -0
  44. package/lib/index.d.ts +9 -0
  45. package/lib/index.d.ts.map +1 -0
  46. package/lib/index.js +53 -0
  47. package/lib/index.js.map +1 -0
  48. package/lib/proxy.d.ts +9 -0
  49. package/lib/proxy.d.ts.map +1 -0
  50. package/lib/proxy.js +116 -0
  51. package/lib/proxy.js.map +1 -0
  52. package/lib/sftp-client.d.ts +12 -0
  53. package/lib/sftp-client.d.ts.map +1 -0
  54. package/lib/sftp-client.js +123 -0
  55. package/lib/sftp-client.js.map +1 -0
  56. package/lib/sftp.d.ts +43 -0
  57. package/lib/sftp.d.ts.map +1 -0
  58. package/lib/sftp.js +251 -0
  59. package/lib/sftp.js.map +1 -0
  60. package/lib/sidebar-anchor.d.ts +8 -0
  61. package/lib/sidebar-anchor.d.ts.map +1 -0
  62. package/lib/sidebar-anchor.js +50 -0
  63. package/lib/sidebar-anchor.js.map +1 -0
  64. package/lib/store.d.ts +20 -0
  65. package/lib/store.d.ts.map +1 -0
  66. package/lib/store.js +154 -0
  67. package/lib/store.js.map +1 -0
  68. package/lib/terminal.d.ts +108 -0
  69. package/lib/terminal.d.ts.map +1 -0
  70. package/lib/terminal.js +384 -0
  71. package/lib/terminal.js.map +1 -0
  72. package/lib/tools.d.ts +7 -0
  73. package/lib/tools.d.ts.map +1 -0
  74. package/lib/tools.js +237 -0
  75. package/lib/tools.js.map +1 -0
  76. package/package.json +107 -0
package/lib/domain.js ADDED
@@ -0,0 +1,136 @@
1
+ export function normalizeProfileDraft(value) {
2
+ const input = record(value, 'profile');
3
+ const authType = input.authType;
4
+ if (authType !== 'password' && authType !== 'private-key' && authType !== 'agent')
5
+ throw bad('authType must be password, private-key, or agent');
6
+ const proxy = normalizeProxy(input.proxy);
7
+ return {
8
+ name: text(input.name, 'name', 1, 80),
9
+ ...optionalText(input.group, 'group', 1, 64),
10
+ host: text(input.host, 'host', 1, 253),
11
+ port: integer(input.port ?? 22, 'port', 1, 65_535),
12
+ username: text(input.username, 'username', 1, 128),
13
+ authType,
14
+ ...optionalText(input.credentialId, 'credentialId', 1, 100),
15
+ ...optionalText(input.hostFingerprint, 'hostFingerprint', 8, 256),
16
+ proxy,
17
+ keepAliveIntervalMs: integer(input.keepAliveIntervalMs ?? 15_000, 'keepAliveIntervalMs', 0, 120_000),
18
+ connectTimeoutMs: integer(input.connectTimeoutMs ?? 15_000, 'connectTimeoutMs', 1000, 120_000),
19
+ terminalType: text(input.terminalType ?? 'xterm-256color', 'terminalType', 1, 64),
20
+ tags: stringArray(input.tags, 'tags', 20, 32),
21
+ };
22
+ }
23
+ export function normalizeCredentialEntryDraft(value) {
24
+ const input = record(value, 'credential entry');
25
+ if (input.authType !== 'password' && input.authType !== 'private-key')
26
+ throw bad('credential authType must be password or private-key');
27
+ return {
28
+ name: text(input.name, 'name', 1, 80),
29
+ username: text(input.username, 'username', 1, 128),
30
+ authType: input.authType,
31
+ };
32
+ }
33
+ export function normalizeForwardDraft(value) {
34
+ const input = record(value, 'forward rule');
35
+ const kind = input.kind;
36
+ if (kind !== 'local' && kind !== 'remote' && kind !== 'dynamic')
37
+ throw bad('kind must be local, remote, or dynamic');
38
+ const targetRequired = kind !== 'dynamic';
39
+ return {
40
+ profileId: text(input.profileId, 'profileId', 1, 100),
41
+ name: text(input.name, 'name', 1, 80),
42
+ kind,
43
+ bindHost: text(input.bindHost ?? (kind === 'remote' ? '127.0.0.1' : '127.0.0.1'), 'bindHost', 1, 253),
44
+ bindPort: integer(input.bindPort, 'bindPort', 0, 65_535),
45
+ ...targetRequired ? {
46
+ targetHost: text(input.targetHost, 'targetHost', 1, 253),
47
+ targetPort: integer(input.targetPort, 'targetPort', 1, 65_535),
48
+ } : {},
49
+ autoStart: input.autoStart === true,
50
+ };
51
+ }
52
+ export function normalizeSecrets(value) {
53
+ const input = value === undefined ? {} : record(value, 'secrets');
54
+ const password = secret(input.password, 'password');
55
+ const privateKey = secret(input.privateKey, 'privateKey', 512_000);
56
+ const passphrase = secret(input.passphrase, 'passphrase');
57
+ const proxyPassword = secret(input.proxyPassword, 'proxyPassword');
58
+ return compactSecrets({
59
+ ...(password === undefined ? {} : { password }),
60
+ ...(privateKey === undefined ? {} : { privateKey }),
61
+ ...(passphrase === undefined ? {} : { passphrase }),
62
+ ...(proxyPassword === undefined ? {} : { proxyPassword }),
63
+ });
64
+ }
65
+ export function compactSecrets(value) {
66
+ return Object.fromEntries(Object.entries(value).filter((entry) => typeof entry[1] === 'string' && entry[1].length > 0));
67
+ }
68
+ export function isLoopbackHost(host) {
69
+ const value = host.trim().toLowerCase().replace(/^\[|\]$/g, '');
70
+ return value === 'localhost' || value === '::1' || value.startsWith('127.');
71
+ }
72
+ function normalizeProxy(value) {
73
+ if (value === undefined || value === null)
74
+ return { type: 'none' };
75
+ const input = record(value, 'proxy');
76
+ if (input.type === 'none')
77
+ return { type: 'none' };
78
+ if (input.type === 'jump') {
79
+ const profileIds = input.profileIds === undefined
80
+ ? [text(input.profileId, 'proxy.profileId', 1, 100)]
81
+ : stringArray(input.profileIds, 'proxy.profileIds', 8, 100);
82
+ if (profileIds.length === 0)
83
+ throw bad('proxy.profileIds must contain at least one jump host');
84
+ return { type: 'jump', profileIds };
85
+ }
86
+ if (input.type === 'http' || input.type === 'socks5') {
87
+ return {
88
+ type: input.type,
89
+ host: text(input.host, 'proxy.host', 1, 253),
90
+ port: integer(input.port, 'proxy.port', 1, 65_535),
91
+ ...optionalText(input.username, 'proxy.username', 1, 128),
92
+ };
93
+ }
94
+ throw bad('proxy.type must be none, http, socks5, or jump');
95
+ }
96
+ function record(value, label) {
97
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
98
+ throw bad(`${label} must be an object`);
99
+ return value;
100
+ }
101
+ function text(value, label, min, max) {
102
+ if (typeof value !== 'string')
103
+ throw bad(`${label} must be a string`);
104
+ const result = value.trim();
105
+ if (result.length < min || result.length > max)
106
+ throw bad(`${label} must contain ${min}-${max} characters`);
107
+ return result;
108
+ }
109
+ function optionalText(value, label, min, max) {
110
+ if (value === undefined || value === null || value === '')
111
+ return {};
112
+ return { [label.split('.').at(-1) ?? label]: text(value, label, min, max) };
113
+ }
114
+ function integer(value, label, min, max) {
115
+ if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < min || value > max)
116
+ throw bad(`${label} must be an integer between ${min} and ${max}`);
117
+ return value;
118
+ }
119
+ function stringArray(value, label, maxItems, maxLength) {
120
+ if (value === undefined)
121
+ return [];
122
+ if (!Array.isArray(value) || value.length > maxItems)
123
+ throw bad(`${label} must be an array with at most ${maxItems} items`);
124
+ return [...new Set(value.map((item, index) => text(item, `${label}[${index}]`, 1, maxLength)))];
125
+ }
126
+ function secret(value, label, max = 65_536) {
127
+ if (value === undefined || value === null || value === '')
128
+ return undefined;
129
+ if (typeof value !== 'string' || value.length > max)
130
+ throw bad(`${label} is invalid`);
131
+ return value;
132
+ }
133
+ function bad(message) {
134
+ return Object.assign(new Error(message), { status: 400 });
135
+ }
136
+ //# sourceMappingURL=domain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domain.js","sourceRoot":"","sources":["../src/domain.ts"],"names":[],"mappings":"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"}
package/lib/exec.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ import { SshConnector } from './connector.js';
2
+ export interface ExecResult {
3
+ profileId: string;
4
+ command: string;
5
+ cwd: string;
6
+ stdout: string;
7
+ stderr: string;
8
+ exitCode: number | null;
9
+ signal: string | null;
10
+ durationMs: number;
11
+ truncated: boolean;
12
+ }
13
+ export declare function executeSshCommand(connector: SshConnector, profileId: string, command: string, timeoutMs: number, maxOutputChars: number, signal?: AbortSignal, cwd?: string): Promise<ExecResult>;
14
+ export declare function directoryPrelude(cwd: string): string;
15
+ //# sourceMappingURL=exec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exec.d.ts","sourceRoot":"","sources":["../src/exec.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAE7C,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,OAAO,CAAA;CACnB;AAED,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,YAAY,EACvB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,MAAM,EACtB,MAAM,CAAC,EAAE,WAAW,EACpB,GAAG,SAAM,GACR,OAAO,CAAC,UAAU,CAAC,CAmBrB;AAyED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAIpD"}
package/lib/exec.js ADDED
@@ -0,0 +1,82 @@
1
+ export async function executeSshCommand(connector, profileId, command, timeoutMs, maxOutputChars, signal, cwd = '~') {
2
+ if (!command.trim())
3
+ throw new Error('command must be non-empty');
4
+ const startedAt = Date.now();
5
+ const connection = await connector.connect(profileId, signal);
6
+ try {
7
+ return await execAndCollect(connection.client, `${directoryPrelude(cwd)} && ${command}`, profileId, command, cwd, startedAt, timeoutMs, maxOutputChars, signal);
8
+ }
9
+ finally {
10
+ connection.close();
11
+ }
12
+ }
13
+ function execAndCollect(client, remoteCommand, profileId, command, cwd, startedAt, timeoutMs, maxOutputChars, signal) {
14
+ return new Promise((resolve, reject) => {
15
+ client.exec(remoteCommand, (error, channel) => {
16
+ if (error) {
17
+ reject(error);
18
+ return;
19
+ }
20
+ collect(channel, profileId, command, cwd, startedAt, timeoutMs, maxOutputChars, signal).then(resolve, reject);
21
+ });
22
+ });
23
+ }
24
+ function collect(channel, profileId, command, cwd, startedAt, timeoutMs, maxOutputChars, signal) {
25
+ return new Promise((resolve, reject) => {
26
+ let stdout = '';
27
+ let stderr = '';
28
+ let exitCode = null;
29
+ let exitSignal = null;
30
+ let truncated = false;
31
+ let settled = false;
32
+ const append = (target, text) => {
33
+ if (target === 'stdout')
34
+ stdout += text;
35
+ else
36
+ stderr += text;
37
+ const total = stdout.length + stderr.length;
38
+ if (total > maxOutputChars) {
39
+ const overflow = total - maxOutputChars;
40
+ if (stderr.length >= overflow)
41
+ stderr = stderr.slice(overflow);
42
+ else {
43
+ const remainder = overflow - stderr.length;
44
+ stderr = '';
45
+ stdout = stdout.slice(remainder);
46
+ }
47
+ truncated = true;
48
+ }
49
+ };
50
+ const cleanup = () => { clearTimeout(timer); signal?.removeEventListener('abort', abort); };
51
+ const finish = () => {
52
+ if (settled)
53
+ return;
54
+ settled = true;
55
+ cleanup();
56
+ resolve({ profileId, command, cwd, stdout, stderr, exitCode, signal: exitSignal, durationMs: Date.now() - startedAt, truncated });
57
+ };
58
+ const fail = (error) => { if (settled)
59
+ return; settled = true; cleanup(); reject(error); };
60
+ const abort = () => { channel.close(); fail(signal?.reason instanceof Error ? signal.reason : new Error('SSH command was aborted')); };
61
+ const timer = setTimeout(() => { channel.close(); fail(Object.assign(new Error(`SSH command timed out after ${timeoutMs} ms`), { code: 'COMMAND_TIMEOUT' })); }, timeoutMs);
62
+ channel.setEncoding('utf8');
63
+ channel.on('data', (chunk) => append('stdout', String(chunk)));
64
+ channel.stderr.setEncoding('utf8');
65
+ channel.stderr.on('data', (chunk) => append('stderr', String(chunk)));
66
+ channel.once('exit', (code, signalName) => { exitCode = code ?? null; exitSignal = signalName ?? null; });
67
+ channel.once('close', finish);
68
+ channel.once('error', fail);
69
+ signal?.addEventListener('abort', abort, { once: true });
70
+ });
71
+ }
72
+ export function directoryPrelude(cwd) {
73
+ if (cwd === '~')
74
+ return 'cd -- "$HOME"';
75
+ if (cwd.startsWith('~/'))
76
+ return `cd -- "$HOME"/${shellQuote(cwd.slice(2))}`;
77
+ return `cd -- ${shellQuote(cwd)}`;
78
+ }
79
+ function shellQuote(value) {
80
+ return `'${value.replace(/'/g, `'"'"'`)}'`;
81
+ }
82
+ //# sourceMappingURL=exec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exec.js","sourceRoot":"","sources":["../src/exec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import { SshConnector } from './connector.js';
2
+ import { SshStore } from './store.js';
3
+ export interface ForwardStatus {
4
+ ruleId: string;
5
+ state: 'stopped' | 'starting' | 'running' | 'error';
6
+ bindHost: string;
7
+ bindPort: number;
8
+ connections: number;
9
+ error?: string;
10
+ }
11
+ export declare class ForwardManager {
12
+ private readonly connector;
13
+ private readonly store;
14
+ private readonly running;
15
+ private readonly failures;
16
+ private readonly starting;
17
+ constructor(connector: SshConnector, store: SshStore);
18
+ list(): ForwardStatus[];
19
+ status(ruleId: string): ForwardStatus;
20
+ start(ruleId: string): Promise<ForwardStatus>;
21
+ stop(ruleId: string): Promise<ForwardStatus>;
22
+ startAuto(): Promise<void>;
23
+ closeAll(): Promise<void>;
24
+ private startFresh;
25
+ }
26
+ //# sourceMappingURL=forwards.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forwards.d.ts","sourceRoot":"","sources":["../src/forwards.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAA6B,MAAM,gBAAgB,CAAA;AAExE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAErC,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,OAAO,CAAA;IACnD,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAWD,qBAAa,cAAc;IAKb,OAAO,CAAC,QAAQ,CAAC,SAAS;IAAgB,OAAO,CAAC,QAAQ,CAAC,KAAK;IAJ5E,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoC;IAC5D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA4B;IACrD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA4C;gBAExC,SAAS,EAAE,YAAY,EAAmB,KAAK,EAAE,QAAQ;IAEtF,IAAI,IAAI,aAAa,EAAE;IAUvB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa;IAMrC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAUvC,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAQ5C,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAI1B,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;YAKjB,UAAU;CAwBzB"}
@@ -0,0 +1,213 @@
1
+ import net from 'node:net';
2
+ import { isLoopbackHost } from './domain.js';
3
+ export class ForwardManager {
4
+ connector;
5
+ store;
6
+ running = new Map();
7
+ failures = new Map();
8
+ starting = new Map();
9
+ constructor(connector, store) {
10
+ this.connector = connector;
11
+ this.store = store;
12
+ }
13
+ list() {
14
+ return this.store.forwards().map(rule => {
15
+ const active = this.running.get(rule.id);
16
+ if (active !== undefined)
17
+ return { ruleId: rule.id, state: 'running', bindHost: rule.bindHost, bindPort: active.bindPort, connections: active.connections };
18
+ if (this.starting.has(rule.id))
19
+ return { ruleId: rule.id, state: 'starting', bindHost: rule.bindHost, bindPort: rule.bindPort, connections: 0 };
20
+ const error = this.failures.get(rule.id);
21
+ return { ruleId: rule.id, state: error === undefined ? 'stopped' : 'error', bindHost: rule.bindHost, bindPort: rule.bindPort, connections: 0, ...error === undefined ? {} : { error } };
22
+ });
23
+ }
24
+ status(ruleId) {
25
+ const result = this.list().find(item => item.ruleId === ruleId);
26
+ if (result === undefined)
27
+ throw Object.assign(new Error('forward rule was not found'), { status: 404 });
28
+ return result;
29
+ }
30
+ start(ruleId) {
31
+ const active = this.running.get(ruleId);
32
+ if (active !== undefined)
33
+ return Promise.resolve(this.status(ruleId));
34
+ const pending = this.starting.get(ruleId);
35
+ if (pending !== undefined)
36
+ return pending;
37
+ const operation = this.startFresh(ruleId).finally(() => this.starting.delete(ruleId));
38
+ this.starting.set(ruleId, operation);
39
+ return operation;
40
+ }
41
+ async stop(ruleId) {
42
+ await this.starting.get(ruleId)?.catch(() => { });
43
+ const active = this.running.get(ruleId);
44
+ if (active !== undefined) {
45
+ this.running.delete(ruleId);
46
+ await active.close();
47
+ }
48
+ this.failures.delete(ruleId);
49
+ return this.status(ruleId);
50
+ }
51
+ async startAuto() {
52
+ for (const rule of this.store.forwards().filter(item => item.autoStart))
53
+ await this.start(rule.id).catch(() => { });
54
+ }
55
+ async closeAll() {
56
+ await Promise.all([...this.running.values()].map(item => item.close().catch(() => { })));
57
+ this.running.clear();
58
+ }
59
+ async startFresh(ruleId) {
60
+ const rule = this.store.forward(ruleId);
61
+ if (rule === undefined)
62
+ throw Object.assign(new Error('forward rule was not found'), { status: 404 });
63
+ const settings = this.store.settings();
64
+ if (!settings.allowPublicBind && !isLoopbackHost(rule.bindHost)) {
65
+ throw Object.assign(new Error('Public port binding is disabled. Use a loopback bind address or enable it in SSH settings.'), { status: 403 });
66
+ }
67
+ const connection = await this.connector.connect(rule.profileId);
68
+ try {
69
+ const running = rule.kind === 'local'
70
+ ? await startLocal(rule, connection)
71
+ : rule.kind === 'dynamic'
72
+ ? await startDynamic(rule, connection)
73
+ : await startRemote(rule, connection);
74
+ this.failures.delete(ruleId);
75
+ this.running.set(ruleId, running);
76
+ return this.status(ruleId);
77
+ }
78
+ catch (error) {
79
+ connection.close();
80
+ const message = error instanceof Error ? error.message : String(error);
81
+ this.failures.set(ruleId, message);
82
+ throw error;
83
+ }
84
+ }
85
+ }
86
+ async function startLocal(rule, connection) {
87
+ const running = baseRunning(rule, connection);
88
+ const server = net.createServer(socket => {
89
+ running.connections += 1;
90
+ socket.once('close', () => { running.connections -= 1; });
91
+ connection.client.forwardOut(socket.remoteAddress ?? '127.0.0.1', socket.remotePort ?? 0, rule.targetHost, rule.targetPort, (error, channel) => {
92
+ if (error)
93
+ return socket.destroy(error);
94
+ pipeSockets(socket, channel);
95
+ });
96
+ });
97
+ running.server = server;
98
+ running.bindPort = await listen(server, rule.bindHost, rule.bindPort);
99
+ running.close = async () => { await closeServer(server); connection.close(); };
100
+ return running;
101
+ }
102
+ async function startDynamic(rule, connection) {
103
+ const running = baseRunning(rule, connection);
104
+ const server = net.createServer(socket => { running.connections += 1; socket.once('close', () => { running.connections -= 1; }); void handleSocksClient(socket, connection.client); });
105
+ running.server = server;
106
+ running.bindPort = await listen(server, rule.bindHost, rule.bindPort);
107
+ running.close = async () => { await closeServer(server); connection.close(); };
108
+ return running;
109
+ }
110
+ async function startRemote(rule, connection) {
111
+ const running = baseRunning(rule, connection);
112
+ const port = await new Promise((resolve, reject) => connection.client.forwardIn(rule.bindHost, rule.bindPort, (error, assignedPort) => error ? reject(error) : resolve(assignedPort)));
113
+ const onConnection = (details, accept, reject) => {
114
+ if (details.destPort !== port)
115
+ return;
116
+ const channel = accept();
117
+ const socket = net.connect({ host: rule.targetHost, port: rule.targetPort });
118
+ running.connections += 1;
119
+ channel.once('close', () => { running.connections -= 1; });
120
+ socket.once('connect', () => pipeSockets(socket, channel));
121
+ socket.once('error', () => { channel.close(); reject(); });
122
+ };
123
+ connection.client.on('tcp connection', onConnection);
124
+ running.bindPort = port;
125
+ running.close = async () => {
126
+ connection.client.off('tcp connection', onConnection);
127
+ await new Promise(resolve => connection.client.unforwardIn(rule.bindHost, port, () => resolve()));
128
+ connection.close();
129
+ };
130
+ return running;
131
+ }
132
+ function baseRunning(rule, connection) {
133
+ return { rule, connection, bindPort: rule.bindPort, connections: 0, close: async () => connection.close() };
134
+ }
135
+ function listen(server, host, port) {
136
+ return new Promise((resolve, reject) => {
137
+ server.once('error', reject);
138
+ server.listen({ host, port, exclusive: true }, () => {
139
+ server.off('error', reject);
140
+ const address = server.address();
141
+ if (address === null || typeof address === 'string')
142
+ return reject(new Error('forward server did not expose a TCP address'));
143
+ resolve(address.port);
144
+ });
145
+ });
146
+ }
147
+ function closeServer(server) {
148
+ return new Promise(resolve => server.close(() => resolve()));
149
+ }
150
+ function pipeSockets(socket, channel) {
151
+ socket.pipe(channel).pipe(socket);
152
+ const close = () => { socket.destroy(); channel.destroy(); };
153
+ socket.once('error', close);
154
+ channel.once('error', close);
155
+ }
156
+ async function handleSocksClient(socket, client) {
157
+ try {
158
+ const greeting = await socketRead(socket, 2);
159
+ if (greeting[0] !== 5)
160
+ throw new Error('not SOCKS5');
161
+ const methods = await socketRead(socket, greeting[1] ?? 0);
162
+ if (!methods.includes(0)) {
163
+ socket.end(Buffer.from([5, 0xff]));
164
+ return;
165
+ }
166
+ socket.write(Buffer.from([5, 0]));
167
+ const request = await socketRead(socket, 4);
168
+ if (request[0] !== 5 || request[1] !== 1)
169
+ throw new Error('unsupported SOCKS5 request');
170
+ let host;
171
+ if (request[3] === 1)
172
+ host = [...await socketRead(socket, 4)].join('.');
173
+ else if (request[3] === 3) {
174
+ const length = (await socketRead(socket, 1))[0] ?? 0;
175
+ host = (await socketRead(socket, length)).toString('utf8');
176
+ }
177
+ else
178
+ throw new Error('unsupported SOCKS5 address');
179
+ const portBuffer = await socketRead(socket, 2);
180
+ const port = ((portBuffer[0] ?? 0) << 8) | (portBuffer[1] ?? 0);
181
+ client.forwardOut(socket.remoteAddress ?? '127.0.0.1', socket.remotePort ?? 0, host, port, (error, channel) => {
182
+ if (error) {
183
+ socket.end(Buffer.from([5, 5, 0, 1, 0, 0, 0, 0, 0, 0]));
184
+ return;
185
+ }
186
+ socket.write(Buffer.from([5, 0, 0, 1, 0, 0, 0, 0, 0, 0]));
187
+ pipeSockets(socket, channel);
188
+ });
189
+ }
190
+ catch {
191
+ socket.destroy();
192
+ }
193
+ }
194
+ function socketRead(socket, length) {
195
+ return new Promise((resolve, reject) => {
196
+ let buffer = Buffer.alloc(0);
197
+ const onData = (chunk) => {
198
+ buffer = Buffer.concat([buffer, chunk]);
199
+ if (buffer.length < length)
200
+ return;
201
+ cleanup();
202
+ const extra = buffer.subarray(length);
203
+ if (extra.length > 0)
204
+ socket.unshift(extra);
205
+ resolve(buffer.subarray(0, length));
206
+ };
207
+ const onError = (error) => { cleanup(); reject(error); };
208
+ const cleanup = () => { socket.off('data', onData); socket.off('error', onError); };
209
+ socket.on('data', onData);
210
+ socket.once('error', onError);
211
+ });
212
+ }
213
+ //# sourceMappingURL=forwards.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forwards.js","sourceRoot":"","sources":["../src/forwards.ts"],"names":[],"mappings":"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"}
package/lib/index.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ import type { Context } from '@deepseek-ai/cordis';
2
+ import { Config as ConfigSchema, type Config as SshConfig } from './config.js';
3
+ export declare const Config: import("@deepseek-ai/schemastery").default<ConfigSchema>;
4
+ export type Config = SshConfig;
5
+ export * from './domain.js';
6
+ export declare const name = "dsh-ssh";
7
+ export declare const inject: string[];
8
+ export declare function apply(context: Context, config: SshConfig): void;
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAElD,OAAO,EAAE,MAAM,IAAI,YAAY,EAAiB,KAAK,MAAM,IAAI,SAAS,EAAE,MAAM,aAAa,CAAA;AAS7F,eAAO,MAAM,MAAM,0DAAe,CAAA;AAClC,MAAM,MAAM,MAAM,GAAG,SAAS,CAAA;AAC9B,cAAc,aAAa,CAAA;AAC3B,eAAO,MAAM,IAAI,YAAY,CAAA;AAC7B,eAAO,MAAM,MAAM,UAA2B,CAAA;AAQ9C,wBAAgB,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,GAAG,IAAI,CAkC/D"}
package/lib/index.js ADDED
@@ -0,0 +1,53 @@
1
+ import { Config as ConfigSchema, resolveConfig } from './config.js';
2
+ import { registerSshApi } from './api.js';
3
+ import { SshConnector } from './connector.js';
4
+ import { SshCredentialVault } from './credentials.js';
5
+ import { ForwardManager } from './forwards.js';
6
+ import { SshStore } from './store.js';
7
+ import { AiTerminalManager, BrowserTerminalManager } from './terminal.js';
8
+ import { registerSshTools } from './tools.js';
9
+ export const Config = ConfigSchema;
10
+ export * from './domain.js';
11
+ export const name = 'dsh-ssh';
12
+ export const inject = ['credentials', 'tools'];
13
+ export function apply(context, config) {
14
+ const ctx = context;
15
+ const resolved = resolveConfig(config);
16
+ ctx.effect(async () => {
17
+ const store = await SshStore.open(resolved.statePath, {
18
+ allowPublicBind: resolved.allowPublicBind,
19
+ defaultCommandTimeoutMs: resolved.defaultCommandTimeoutMs,
20
+ maxOutputChars: resolved.maxOutputChars,
21
+ });
22
+ const credentials = new SshCredentialVault(ctx.credentials);
23
+ const connector = new SshConnector(store, credentials);
24
+ const forwards = new ForwardManager(connector, store);
25
+ const terminals = new BrowserTerminalManager(connector);
26
+ const aiTerminals = new AiTerminalManager(connector);
27
+ registerSshTools(context, store, connector, forwards, aiTerminals);
28
+ let disposeApi;
29
+ const mountApi = (runtime) => {
30
+ if (!resolved.exposeWeb)
31
+ return;
32
+ const webServer = runtime.webServer ?? runtime.get('webServer');
33
+ if (webServer === undefined)
34
+ throw new Error('dsh-ssh exposeWeb requires webServer');
35
+ disposeApi = registerSshApi(webServer, resolved.apiPrefix, { store, credentials, connector, forwards, terminals, aiTerminals });
36
+ };
37
+ if (ctx.inject !== undefined)
38
+ ctx.inject(['webServer'], mountApi);
39
+ else if (ctx.webServer !== undefined)
40
+ mountApi(ctx);
41
+ else
42
+ ctx.logger.warn('dsh-ssh: webServer is unavailable; browser management is disabled');
43
+ await forwards.startAuto();
44
+ ctx.logger.info(`dsh-ssh: ready with ${store.profiles().length} profiles`);
45
+ return async () => {
46
+ disposeApi?.();
47
+ await terminals.closeAll();
48
+ await aiTerminals.closeAll();
49
+ await forwards.closeAll();
50
+ };
51
+ }, 'dsh-ssh.runtime');
52
+ }
53
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,aAAa,EAA4B,MAAM,aAAa,CAAA;AAC7F,OAAO,EAAE,cAAc,EAAsB,MAAM,UAAU,CAAA;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAA;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAE7C,MAAM,CAAC,MAAM,MAAM,GAAG,YAAY,CAAA;AAElC,cAAc,aAAa,CAAA;AAC3B,MAAM,CAAC,MAAM,IAAI,GAAG,SAAS,CAAA;AAC7B,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,aAAa,EAAE,OAAO,CAAC,CAAA;AAQ9C,MAAM,UAAU,KAAK,CAAC,OAAgB,EAAE,MAAiB;IACvD,MAAM,GAAG,GAAG,OAAyB,CAAA;IACrC,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,CAAA;IACtC,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE;QACpB,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE;YACpD,eAAe,EAAE,QAAQ,CAAC,eAAe;YACzC,uBAAuB,EAAE,QAAQ,CAAC,uBAAuB;YACzD,cAAc,EAAE,QAAQ,CAAC,cAAc;SACxC,CAAC,CAAA;QACF,MAAM,WAAW,GAAG,IAAI,kBAAkB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QAC3D,MAAM,SAAS,GAAG,IAAI,YAAY,CAAC,KAAK,EAAE,WAAW,CAAC,CAAA;QACtD,MAAM,QAAQ,GAAG,IAAI,cAAc,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;QACrD,MAAM,SAAS,GAAG,IAAI,sBAAsB,CAAC,SAAS,CAAC,CAAA;QACvD,MAAM,WAAW,GAAG,IAAI,iBAAiB,CAAC,SAAS,CAAC,CAAA;QACpD,gBAAgB,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAA;QAClE,IAAI,UAAoC,CAAA;QACxC,MAAM,QAAQ,GAAG,CAAC,OAAuB,EAAQ,EAAE;YACjD,IAAI,CAAC,QAAQ,CAAC,SAAS;gBAAE,OAAM;YAC/B,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,CAA8B,CAAA;YAC5F,IAAI,SAAS,KAAK,SAAS;gBAAE,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAA;YACpF,UAAU,GAAG,cAAc,CAAC,SAAS,EAAE,QAAQ,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,CAAA;QACjI,CAAC,CAAA;QACD,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS;YAAE,GAAG,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,EAAE,QAAQ,CAAC,CAAA;aAC5D,IAAI,GAAG,CAAC,SAAS,KAAK,SAAS;YAAE,QAAQ,CAAC,GAAG,CAAC,CAAA;;YAC9C,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,mEAAmE,CAAC,CAAA;QACzF,MAAM,QAAQ,CAAC,SAAS,EAAE,CAAA;QAC1B,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,uBAAuB,KAAK,CAAC,QAAQ,EAAE,CAAC,MAAM,WAAW,CAAC,CAAA;QAC1E,OAAO,KAAK,IAAI,EAAE;YAChB,UAAU,EAAE,EAAE,CAAA;YACd,MAAM,SAAS,CAAC,QAAQ,EAAE,CAAA;YAC1B,MAAM,WAAW,CAAC,QAAQ,EAAE,CAAA;YAC5B,MAAM,QAAQ,CAAC,QAAQ,EAAE,CAAA;QAC3B,CAAC,CAAA;IACH,CAAC,EAAE,iBAAiB,CAAC,CAAA;AACvB,CAAC"}
package/lib/proxy.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ import { type Socket } from 'node:net';
2
+ export interface ProxyCredentials {
3
+ username?: string;
4
+ password?: string;
5
+ }
6
+ export declare function connectHttpProxy(proxyHost: string, proxyPort: number, targetHost: string, targetPort: number, credentials: ProxyCredentials, timeoutMs: number): Promise<Socket>;
7
+ export declare function connectSocks5Proxy(proxyHost: string, proxyPort: number, targetHost: string, targetPort: number, credentials: ProxyCredentials, timeoutMs: number): Promise<Socket>;
8
+ export declare function connectSocket(host: string, port: number, timeoutMs: number): Promise<Socket>;
9
+ //# sourceMappingURL=proxy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AACA,OAAY,EAAE,KAAK,MAAM,EAAE,MAAM,UAAU,CAAA;AAE3C,MAAM,WAAW,gBAAgB;IAAG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE;AAE1E,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,gBAAgB,EAC7B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC,CAgBjB;AAED,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,gBAAgB,EAC7B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC,CAgCjB;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAQlG"}