@hyzyn/dsh-tty 0.2.1 → 0.9.0

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/lib/sftp.js ADDED
@@ -0,0 +1,449 @@
1
+ /**
2
+ * @hyzyn/dsh-tty — SFTP 文件传输(0.7.0)。
3
+ *
4
+ * 懒连接池:按「解析后的 SshSpec 签名」缓存 ssh2 Client + SFTPWrapper,首次操作
5
+ * 才建连,空闲 SFTP_IDLE_MS 由 unref 定时器回收;连接 error/close 即丢弃条目,
6
+ * 下次操作自动重连(不做后台重连循环——SFTP 没有常驻监听需求,与隧道不同;
7
+ * 解析 spec 由调用方每次传入,连接簿凭证热改后天然生效)。
8
+ *
9
+ * 连接建立复用 buildConnectConfig + applyHostKeyPolicy——TOFU 与终端会话、
10
+ * 隧道共用同一 HostKeyStore,指纹变更同样拒绝且文案一致;password 认证挂
11
+ * keyboard-interactive 自动应答(同 spawnSsh,很多服务端只开这个)。
12
+ *
13
+ * 文件操作走 SFTPWrapper:目录列表(realpath 解析 home)/ stat / mkdir
14
+ * (parents:true 逐级补齐,0.8.0)/ rename / remove(目录递归 = readdir
15
+ * 深度优先 unlink + rmdir)/ tree(递归列举,0.8.0)/ 上传下载直接给流
16
+ * (HTTP 路由 pipe,不整文件进内存)。不计入 maxSessions 名额
17
+ * (同端口转发);SFTP 的权限边界与 SSH 终端登录一致(同一账号)。
18
+ */
19
+ import { Client } from 'ssh2';
20
+ import { createReadStream, createWriteStream } from 'node:fs';
21
+ import { mkdir as fsMkdir, readdir as fsReaddir, stat as fsStat } from 'node:fs/promises';
22
+ import { basename, dirname, join as pathJoin } from 'node:path';
23
+ import { pipeline } from 'node:stream/promises';
24
+ import { applyHostKeyPolicy, buildConnectConfig, sshTarget } from './ssh.js';
25
+ /** 连接空闲回收阈值:窗口内无任何操作即断开(下次操作自动重连)。 */
26
+ const SFTP_IDLE_MS = 120_000;
27
+ /** 扫描周期。 */
28
+ const SFTP_SWEEP_MS = 30_000;
29
+ /** OpenSSH 等 server 的 readdir 会带回 '.'/'..':目录列表与递归删除都要跳过。 */
30
+ const DOT_ENTRIES = new Set(['.', '..']);
31
+ /** 远程路径拼接(POSIX 语义;本机路径拼接用 node:path)。 */
32
+ function joinRemotePath(base, name) {
33
+ return (base.endsWith('/') ? base : base + '/') + name;
34
+ }
35
+ function signatureOf(spec) {
36
+ return JSON.stringify(spec);
37
+ }
38
+ export class SftpManager {
39
+ logger;
40
+ store;
41
+ conns = new Map();
42
+ sweeper = null;
43
+ constructor(logger, store) {
44
+ this.logger = logger;
45
+ this.store = store;
46
+ }
47
+ /** 插件卸载:关定时器与全部连接(幂等)。 */
48
+ disposeAll() {
49
+ if (this.sweeper !== null) {
50
+ clearInterval(this.sweeper);
51
+ this.sweeper = null;
52
+ }
53
+ for (const rt of this.conns.values())
54
+ this.close(rt);
55
+ this.conns.clear();
56
+ }
57
+ /* -------------------------------------------------------------- */
58
+ /* 文件操作 */
59
+ /* -------------------------------------------------------------- */
60
+ /** 目录列表;path 为空时 realpath('.') 解析登录 home 并回传实际路径。 */
61
+ async list(spec, path) {
62
+ const sftp = await this.acquire(spec);
63
+ const trimmed = path.trim();
64
+ const resolved = trimmed === '' ? await this.realpath(sftp, '.') : trimmed;
65
+ // OpenSSH 等 server 的 readdir 会带回 '.'/'..',客户端 UI 自绘「上级目录」行,这里过滤防重复
66
+ const raw = (await this.readdir(sftp, resolved)).filter((item) => !DOT_ENTRIES.has(item.filename));
67
+ const entries = raw.map((item) => ({
68
+ name: item.filename,
69
+ isDir: item.attrs.isDirectory(),
70
+ isFile: item.attrs.isFile(),
71
+ isSymlink: item.attrs.isSymbolicLink(),
72
+ size: Number(item.attrs.size ?? 0),
73
+ mtime: Number(item.attrs.mtime ?? 0) * 1000,
74
+ }));
75
+ entries.sort((a, b) => {
76
+ const kindDiff = (a.isDir ? 0 : 1) - (b.isDir ? 0 : 1);
77
+ if (kindDiff !== 0)
78
+ return kindDiff;
79
+ return a.name.localeCompare(b.name);
80
+ });
81
+ return { path: resolved, entries };
82
+ }
83
+ /**
84
+ * 创建目录。parents:true 时等效 mkdir -p(自底向上):先直接建目标,
85
+ * 失败且目标确不存在时向最近的祖先逐级补齐——不从文件系统根逐级 stat
86
+ * (往返少,也不要求对中间层级有探测权限);「已存在且是目录」视为
87
+ * 成功,同名非目录明确报错;补齐后重试仍失败再兜底 stat 防并发竞态。
88
+ */
89
+ async mkdir(spec, path, parents = false) {
90
+ const sftp = await this.acquire(spec);
91
+ const target = path.trim().replace(/\/+$/, '');
92
+ if (target === '')
93
+ throw new Error('创建目录失败: 路径不能为空');
94
+ if (!parents) {
95
+ await this.mkdirOne(sftp, target);
96
+ return;
97
+ }
98
+ const isAbsolute = target.startsWith('/');
99
+ const segments = target.split('/').filter((seg) => seg !== '' && seg !== '.');
100
+ if (segments.length === 0)
101
+ return; // 根目录本身总是存在的
102
+ const join = (depth) => {
103
+ const prefix = segments.slice(0, depth).join('/');
104
+ return isAbsolute ? '/' + prefix : prefix;
105
+ };
106
+ const ensure = async (depth) => {
107
+ const current = join(depth);
108
+ try {
109
+ await this.mkdirOne(sftp, current);
110
+ return;
111
+ }
112
+ catch (firstError) {
113
+ const existing = await this.statQuiet(sftp, current);
114
+ if (existing !== null) {
115
+ if (existing.isDirectory())
116
+ return;
117
+ throw new Error(`创建目录失败: ${current} 已存在且不是目录`);
118
+ }
119
+ if (depth > 1) {
120
+ await ensure(depth - 1);
121
+ try {
122
+ await this.mkdirOne(sftp, current);
123
+ return;
124
+ }
125
+ catch {
126
+ /* 落到兜底 stat(并发创建等竞态) */
127
+ }
128
+ const raced = await this.statQuiet(sftp, current);
129
+ if (raced !== null && raced.isDirectory())
130
+ return;
131
+ }
132
+ throw firstError;
133
+ }
134
+ };
135
+ await ensure(segments.length);
136
+ }
137
+ /**
138
+ * 递归列举(agent sftp_tree 用):深度优先、目录优先(与 list 同排序),
139
+ * maxDepth(1~8,默认 3)限层、maxEntries(1~2000,默认 500)限条数,
140
+ * 超限置 truncated;符号链接不跟随(防环),仅作条目呈现;读取失败的
141
+ * 子目录记入 errors(权限等)并继续。
142
+ */
143
+ async tree(spec, path, options = {}) {
144
+ const maxDepth = Math.max(1, Math.min(8, Number.isInteger(options.maxDepth) ? options.maxDepth : 3));
145
+ const maxEntries = Math.max(1, Math.min(2000, Number.isInteger(options.maxEntries) ? options.maxEntries : 500));
146
+ const sftp = await this.acquire(spec);
147
+ const trimmed = path.trim();
148
+ const root = trimmed === '' ? await this.realpath(sftp, '.') : trimmed === '/' ? '/' : trimmed.replace(/\/+$/, '');
149
+ const entries = [];
150
+ const errors = [];
151
+ let truncated = false;
152
+ const walk = async (dir, depth, isRoot = false) => {
153
+ let list;
154
+ try {
155
+ list = (await this.readdir(sftp, dir)).filter((item) => !DOT_ENTRIES.has(item.filename));
156
+ }
157
+ catch (error) {
158
+ // 请求的根目录读不到(不存在/权限)→ 明确报错;子目录失败记入 errors 继续
159
+ if (isRoot)
160
+ throw new Error(`读取目录失败: ${error instanceof Error ? error.message : String(error)}`);
161
+ errors.push({ path: dir, message: error instanceof Error ? error.message : String(error) });
162
+ return;
163
+ }
164
+ list.sort((a, b) => {
165
+ const kindDiff = (a.attrs.isDirectory() ? 0 : 1) - (b.attrs.isDirectory() ? 0 : 1);
166
+ if (kindDiff !== 0)
167
+ return kindDiff;
168
+ return a.filename.localeCompare(b.filename);
169
+ });
170
+ for (const item of list) {
171
+ if (entries.length >= maxEntries) {
172
+ truncated = true;
173
+ return;
174
+ }
175
+ const isDir = item.attrs.isDirectory();
176
+ const isSymlink = item.attrs.isSymbolicLink();
177
+ entries.push({
178
+ path: dir.endsWith('/') ? dir + item.filename : dir + '/' + item.filename,
179
+ name: item.filename,
180
+ depth,
181
+ isDir,
182
+ size: Number(item.attrs.size ?? 0),
183
+ mtime: Number(item.attrs.mtime ?? 0) * 1000,
184
+ });
185
+ if (isDir && !isSymlink) {
186
+ if (depth + 1 > maxDepth) {
187
+ truncated = true;
188
+ continue;
189
+ }
190
+ await walk(dir.endsWith('/') ? dir + item.filename : dir + '/' + item.filename, depth + 1);
191
+ }
192
+ }
193
+ };
194
+ await walk(root, 1, true);
195
+ return { path: root, entries, truncated, errors: errors.slice(0, 10) };
196
+ }
197
+ async rename(spec, from, to) {
198
+ const sftp = await this.acquire(spec);
199
+ await new Promise((resolve, reject) => {
200
+ sftp.rename(from.trim(), to.trim(), (error) => (error != null ? reject(new Error(`重命名失败: ${error.message}`)) : resolve()));
201
+ });
202
+ }
203
+ /**
204
+ * 删除文件 / 目录。目录不带 recursive 时走 rmdir(非空会明确报错);
205
+ * 带 recursive 时 readdir 深度优先逐个 unlink/rmdir。符号链接一律按
206
+ * 文件 unlink(不跟随)。
207
+ */
208
+ async remove(spec, path, recursive) {
209
+ const sftp = await this.acquire(spec);
210
+ await this.removeEntry(sftp, path.trim(), recursive);
211
+ }
212
+ /** 下载:返回只读流(路由负责 pipe 到 HTTP 响应与销毁)。 */
213
+ async openDownload(spec, path) {
214
+ const sftp = await this.acquire(spec);
215
+ const target = path.trim();
216
+ let size = null;
217
+ try {
218
+ const stats = await new Promise((resolve, reject) => {
219
+ sftp.stat(target, (error, stats) => (error !== undefined ? reject(error) : resolve(stats)));
220
+ });
221
+ if (stats.isFile())
222
+ size = Number(stats.size ?? 0);
223
+ }
224
+ catch {
225
+ /* stat 失败不阻塞下载(content-length 缺省,流式传输照常) */
226
+ }
227
+ const stream = sftp.createReadStream(target);
228
+ return { stream, size };
229
+ }
230
+ /** 上传:返回可写流与完成信号(路由 pipe 请求体,await done 后回包)。 */
231
+ async openUpload(spec, path, append = false) {
232
+ const sftp = await this.acquire(spec);
233
+ const stream = sftp.createWriteStream(path.trim(), { flags: append ? 'a' : 'w' });
234
+ const done = new Promise((resolve, reject) => {
235
+ stream.on('error', (error) => {
236
+ reject(new Error(`上传写入失败: ${error.message}`));
237
+ });
238
+ stream.on('close', () => resolve());
239
+ });
240
+ return { stream, done };
241
+ }
242
+ /* -------------------------------------------------------------- */
243
+ /* 双栏直传(0.9.0):本机路径 ↔ 远程路径,服务端流式搬运 */
244
+ /* -------------------------------------------------------------- */
245
+ /**
246
+ * 本机文件 / 目录 → 远程(双栏「→ 传输」)。目录递归建目录后逐个上传;
247
+ * 同名文件直接覆盖(openUpload 'w')。不经过浏览器,字节不出宿主进程。
248
+ */
249
+ async uploadFromLocal(spec, localPath, remotePath) {
250
+ const root = localPath.trim();
251
+ const info = await fsStat(root).catch(() => {
252
+ throw new Error('本机路径不存在: ' + root);
253
+ });
254
+ if (info.isDirectory()) {
255
+ await this.mkdir(spec, remotePath, true);
256
+ const children = await fsReaddir(root, { withFileTypes: true });
257
+ for (const child of children) {
258
+ await this.uploadFromLocal(spec, pathJoin(root, child.name), joinRemotePath(remotePath, child.name));
259
+ }
260
+ return;
261
+ }
262
+ if (!info.isFile())
263
+ throw new Error('不支持传输的文件类型: ' + root);
264
+ const { stream, done } = await this.openUpload(spec, remotePath, false);
265
+ await pipeline(createReadStream(root), stream).catch((error) => {
266
+ throw new Error(`上传失败(${basename(root)}): ${error instanceof Error ? error.message : String(error)}`);
267
+ });
268
+ await done;
269
+ }
270
+ /**
271
+ * 远程文件 / 目录 → 本机(双栏「← 传输」)。目录递归建本地目录后逐个下载;
272
+ * 同名文件直接覆盖('w' 写流)。远程符号链接按文件下载(跟随目标)。
273
+ */
274
+ async downloadToLocal(spec, remotePath, localPath) {
275
+ const target = remotePath.trim();
276
+ const sftp = await this.acquire(spec);
277
+ const stats = await new Promise((resolve, reject) => {
278
+ sftp.stat(target, (error, found) => (error != null ? reject(new Error(`远程路径不存在: ${target}(${error.message})`)) : resolve(found)));
279
+ });
280
+ if (stats.isDirectory()) {
281
+ await fsMkdir(localPath, { recursive: true });
282
+ const list = await this.list(spec, target);
283
+ for (const entry of list.entries) {
284
+ if (DOT_ENTRIES.has(entry.name))
285
+ continue;
286
+ await this.downloadToLocal(spec, joinRemotePath(target, entry.name), pathJoin(localPath, entry.name));
287
+ }
288
+ return;
289
+ }
290
+ await fsMkdir(dirname(localPath), { recursive: true });
291
+ const { stream } = await this.openDownload(spec, target);
292
+ await pipeline(stream, createWriteStream(localPath)).catch((error) => {
293
+ throw new Error(`下载失败(${basename(target)}): ${error instanceof Error ? error.message : String(error)}`);
294
+ });
295
+ }
296
+ /* -------------------------------------------------------------- */
297
+ /* 连接池 */
298
+ /* -------------------------------------------------------------- */
299
+ /** 取(或建立)该 spec 的 SFTP 通道;连接断开的旧条目在此处自动重建。 */
300
+ async acquire(spec) {
301
+ this.ensureSweeper();
302
+ const signature = signatureOf(spec);
303
+ const existing = this.conns.get(signature);
304
+ if (existing !== undefined) {
305
+ existing.lastUsed = Date.now();
306
+ return existing.sftp;
307
+ }
308
+ const target = sshTarget(spec);
309
+ const conn = new Client();
310
+ let sftp;
311
+ try {
312
+ const connectConfig = buildConnectConfig(spec);
313
+ const policy = applyHostKeyPolicy({ connectConfig, spec, store: this.store, logger: this.logger, target });
314
+ // password 认证挂 keyboard-interactive 自动应答(同 spawnSsh;
315
+ // tryKeyboard 只在 password 分支置位,见 buildConnectConfig)
316
+ if (connectConfig.tryKeyboard === true) {
317
+ const password = connectConfig.password ?? '';
318
+ conn.on('keyboard-interactive', (_name, _instructions, _lang, _prompts, finishKb) => {
319
+ finishKb([password]);
320
+ });
321
+ }
322
+ await new Promise((resolve, reject) => {
323
+ let settled = false;
324
+ conn.on('ready', () => {
325
+ settled = true;
326
+ resolve();
327
+ });
328
+ conn.on('error', (error) => {
329
+ if (!settled) {
330
+ settled = true;
331
+ const mismatch = policy.mismatchMessage();
332
+ reject(new Error(mismatch ?? `SSH 连接失败(${target}): ${error.message}`));
333
+ }
334
+ else {
335
+ this.logger.warn(`[dsh-tty] sftp ${target} 连接错误: ${error.message}`);
336
+ }
337
+ });
338
+ conn.on('close', () => {
339
+ // 连接断开:丢弃池内条目,下次操作自动重连
340
+ const rt = this.conns.get(signature);
341
+ if (rt !== undefined && rt.conn === conn)
342
+ this.conns.delete(signature);
343
+ });
344
+ try {
345
+ conn.connect(connectConfig);
346
+ }
347
+ catch (error) {
348
+ reject(error instanceof Error ? error : new Error(String(error)));
349
+ }
350
+ });
351
+ sftp = await new Promise((resolve, reject) => {
352
+ conn.sftp((error, channel) => {
353
+ if (error !== undefined && error !== null)
354
+ reject(new Error(`sftp channel 打开失败: ${error.message}`));
355
+ else
356
+ resolve(channel);
357
+ });
358
+ });
359
+ }
360
+ catch (error) {
361
+ try {
362
+ conn.end();
363
+ }
364
+ catch {
365
+ /* 未建立 */
366
+ }
367
+ throw error;
368
+ }
369
+ this.logger.info(`[dsh-tty] sftp ${target} 就绪`);
370
+ const rt = { spec, signature, conn, sftp, lastUsed: Date.now() };
371
+ this.conns.set(signature, rt);
372
+ return sftp;
373
+ }
374
+ ensureSweeper() {
375
+ if (this.sweeper !== null)
376
+ return;
377
+ this.sweeper = setInterval(() => {
378
+ const now = Date.now();
379
+ for (const [signature, rt] of [...this.conns.entries()]) {
380
+ if (now - rt.lastUsed > SFTP_IDLE_MS) {
381
+ this.logger.info(`[dsh-tty] sftp ${sshTarget(rt.spec)} 空闲回收`);
382
+ this.conns.delete(signature);
383
+ this.close(rt);
384
+ }
385
+ }
386
+ }, SFTP_SWEEP_MS);
387
+ this.sweeper.unref?.();
388
+ }
389
+ close(rt) {
390
+ try {
391
+ rt.conn.end();
392
+ }
393
+ catch {
394
+ /* 已断开 */
395
+ }
396
+ }
397
+ /* -------------------------------------------------------------- */
398
+ /* SFTPWrapper 回调的 Promise 化与递归删除 */
399
+ /* -------------------------------------------------------------- */
400
+ realpath(sftp, path) {
401
+ return new Promise((resolve, reject) => {
402
+ sftp.realpath(path, (error, absPath) => (error !== undefined ? reject(new Error(`realpath 失败: ${error.message}`)) : resolve(absPath)));
403
+ });
404
+ }
405
+ /** stat 的静默版:路径不存在等错误一律回 null(mkdir -p 的逐级探测用)。 */
406
+ statQuiet(sftp, path) {
407
+ return new Promise((resolve) => {
408
+ sftp.stat(path, (error, stats) => (error !== undefined || stats === undefined ? resolve(null) : resolve(stats)));
409
+ });
410
+ }
411
+ mkdirOne(sftp, path) {
412
+ return new Promise((resolve, reject) => {
413
+ sftp.mkdir(path, (error) => (error != null ? reject(new Error(`创建目录失败: ${error.message}`)) : resolve()));
414
+ });
415
+ }
416
+ readdir(sftp, path) {
417
+ return new Promise((resolve, reject) => {
418
+ sftp.readdir(path, (error, list) => (error !== undefined ? reject(new Error(`读取目录失败: ${error.message}`)) : resolve(list)));
419
+ });
420
+ }
421
+ async removeEntry(sftp, path, recursive) {
422
+ const stats = await new Promise((resolve, reject) => {
423
+ sftp.lstat(path, (error, stats) => (error !== undefined ? reject(new Error(`删除失败: ${error.message}`)) : resolve(stats)));
424
+ });
425
+ if (!stats.isDirectory()) {
426
+ await new Promise((resolve, reject) => {
427
+ sftp.unlink(path, (error) => (error != null ? reject(new Error(`删除失败: ${error.message}`)) : resolve()));
428
+ });
429
+ return;
430
+ }
431
+ if (!recursive) {
432
+ await new Promise((resolve, reject) => {
433
+ sftp.rmdir(path, (error) => (error != null ? reject(new Error(`删除目录失败(非空目录需 recursive): ${error.message}`)) : resolve()));
434
+ });
435
+ return;
436
+ }
437
+ const children = await this.readdir(sftp, path);
438
+ const base = path.endsWith('/') ? path : path + '/';
439
+ for (const child of children) {
440
+ if (DOT_ENTRIES.has(child.filename))
441
+ continue;
442
+ await this.removeEntry(sftp, base + child.filename, true);
443
+ }
444
+ await new Promise((resolve, reject) => {
445
+ sftp.rmdir(path, (error) => (error != null ? reject(new Error(`删除目录失败: ${error.message}`)) : resolve()));
446
+ });
447
+ }
448
+ }
449
+ //# sourceMappingURL=sftp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sftp.js","sourceRoot":"","sources":["../src/sftp.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /** shell 集成的 spawn 片段:argv(-c 包装层)与额外 env。 */
2
+ export interface ShellSpawnPlan {
3
+ argv: string[];
4
+ env: Record<string, string>;
5
+ }
6
+ /**
7
+ * 组装 shell 启动计划:在原有 TERM/COLORTERM 包装层之上,按 shell basename
8
+ * 注入集成(zsh → ZDOTDIR 桩;bash → --rcfile 桩)。integration=false 或不
9
+ * 支持的 shell 返回最简包装层。
10
+ */
11
+ export declare function buildShellSpawn(shell: string, term: string, colorTerm: string, integration: boolean): ShellSpawnPlan;