xshell 1.3.1 → 1.3.3
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/file.d.ts +0 -27
- package/file.js +1 -85
- package/fzip.d.ts +28 -0
- package/fzip.js +91 -0
- package/net.common.d.ts +5 -2
- package/net.common.js +7 -2
- package/package.json +1 -1
package/file.d.ts
CHANGED
|
@@ -218,33 +218,6 @@ export declare function flink(fp_real: string, fp_link: string, { skip_existing,
|
|
|
218
218
|
print?: boolean;
|
|
219
219
|
junction?: boolean;
|
|
220
220
|
}): Promise<void>;
|
|
221
|
-
export interface ZipOptions {
|
|
222
|
-
dirname?: string;
|
|
223
|
-
print?: {
|
|
224
|
-
info: boolean;
|
|
225
|
-
files: boolean;
|
|
226
|
-
};
|
|
227
|
-
}
|
|
228
|
-
/** 将文件夹或文件列表压缩为 zip,返回生成的压缩包路径 (fp_zip)
|
|
229
|
-
- data:
|
|
230
|
-
- fpd_src: 被压缩文件夹路径 (string) 或
|
|
231
|
-
- entries: 文件列表 (Record<压缩后相对路径, 原文件绝对路径 (string) | 数据 (Uint8Array)>)
|
|
232
|
-
- fp_zip: 生成的压缩包路径 (string)
|
|
233
|
-
- options?:
|
|
234
|
-
- dirname?: `fpd_src.fname` 传入 fpd_src 才生效,修改 zip 中顶层的文件夹的名字(需要以 / 结尾),如 'web/', 为空字符串时去掉顶层文件夹,不要多一个文件夹层级 (flat)
|
|
235
|
-
- print?:
|
|
236
|
-
- info?: `true` 开始压缩、压缩完成
|
|
237
|
-
- files?: `true` 打印压缩文件列表 */
|
|
238
|
-
export declare function fzip(data: string | Record<string, string | Uint8Array>, fp_zip: string, options?: ZipOptions): Promise<string>;
|
|
239
|
-
/** 将文件夹或文件列表压缩为 zip,返回压缩包数据 (Uint8Array)
|
|
240
|
-
- data:
|
|
241
|
-
- fpd_src: 被压缩文件夹路径 (string) 或
|
|
242
|
-
- entries: 文件列表 (Record<压缩后相对路径, 原文件绝对路径 (string) | 数据 (Uint8Array)>)
|
|
243
|
-
- options?:
|
|
244
|
-
- print?:
|
|
245
|
-
- info?: `true` 开始压缩、压缩完成
|
|
246
|
-
- files?: `true` 打印压缩文件列表 */
|
|
247
|
-
export declare function zip(data: string | Record<string, string | Uint8Array>, options?: ZipOptions): Promise<Buffer>;
|
|
248
221
|
export interface UnzipOptions {
|
|
249
222
|
encoding?: Encoding;
|
|
250
223
|
dryrun?: boolean;
|
package/file.js
CHANGED
|
@@ -4,7 +4,7 @@ import { t } from "./i18n/instance.js";
|
|
|
4
4
|
import { noop, to_json } from "./prototype.js";
|
|
5
5
|
import { pack, parse } from "./io.common.js";
|
|
6
6
|
import { path } from "./path.js";
|
|
7
|
-
import { check, Lock,
|
|
7
|
+
import { check, Lock, url_width, throttle, decode, strcmp } from "./utils.js";
|
|
8
8
|
import { noprint } from "./process.js";
|
|
9
9
|
export { fsp };
|
|
10
10
|
export const encodings = ['utf-8', 'gb18030', 'shift-jis', 'utf-16le'];
|
|
@@ -481,90 +481,6 @@ export async function flink(fp_real, fp_link, { skip_existing = false, print = t
|
|
|
481
481
|
else
|
|
482
482
|
await fsp.symlink(fp_real, fp_link, is_fpd_real ? 'dir' : 'file');
|
|
483
483
|
}
|
|
484
|
-
/** 将文件夹或文件列表压缩为 zip,返回生成的压缩包路径 (fp_zip)
|
|
485
|
-
- data:
|
|
486
|
-
- fpd_src: 被压缩文件夹路径 (string) 或
|
|
487
|
-
- entries: 文件列表 (Record<压缩后相对路径, 原文件绝对路径 (string) | 数据 (Uint8Array)>)
|
|
488
|
-
- fp_zip: 生成的压缩包路径 (string)
|
|
489
|
-
- options?:
|
|
490
|
-
- dirname?: `fpd_src.fname` 传入 fpd_src 才生效,修改 zip 中顶层的文件夹的名字(需要以 / 结尾),如 'web/', 为空字符串时去掉顶层文件夹,不要多一个文件夹层级 (flat)
|
|
491
|
-
- print?:
|
|
492
|
-
- info?: `true` 开始压缩、压缩完成
|
|
493
|
-
- files?: `true` 打印压缩文件列表 */
|
|
494
|
-
export async function fzip(data, fp_zip, options) {
|
|
495
|
-
return _zip(data, fp_zip, options);
|
|
496
|
-
}
|
|
497
|
-
/** 将文件夹或文件列表压缩为 zip,返回压缩包数据 (Uint8Array)
|
|
498
|
-
- data:
|
|
499
|
-
- fpd_src: 被压缩文件夹路径 (string) 或
|
|
500
|
-
- entries: 文件列表 (Record<压缩后相对路径, 原文件绝对路径 (string) | 数据 (Uint8Array)>)
|
|
501
|
-
- options?:
|
|
502
|
-
- print?:
|
|
503
|
-
- info?: `true` 开始压缩、压缩完成
|
|
504
|
-
- files?: `true` 打印压缩文件列表 */
|
|
505
|
-
export async function zip(data, options) {
|
|
506
|
-
return _zip(data, undefined, options);
|
|
507
|
-
}
|
|
508
|
-
async function _zip(data, fp_zip, { dirname, print = { files: true, info: true } } = {}) {
|
|
509
|
-
let entries;
|
|
510
|
-
let fpd_src;
|
|
511
|
-
if (typeof data === 'string') {
|
|
512
|
-
if (!path.isAbsolute(data) || !data.isdir)
|
|
513
|
-
throw new Error('fpd_src 必须是绝对路径且以 / 结尾');
|
|
514
|
-
fpd_src = data;
|
|
515
|
-
if (dirname === undefined)
|
|
516
|
-
dirname = fpd_src.fname;
|
|
517
|
-
if (!dirname.isdir)
|
|
518
|
-
throw new Error('dirname 需要以 / 结尾');
|
|
519
|
-
entries = Object.fromEntries((await flist(fpd_src, noprint))
|
|
520
|
-
.map(fp => ([dirname + fp, fpd_src + fp])));
|
|
521
|
-
}
|
|
522
|
-
else {
|
|
523
|
-
check(!dirname, 'dirname 在传入 fpd_src 时才生效');
|
|
524
|
-
entries = data;
|
|
525
|
-
}
|
|
526
|
-
if (print.info)
|
|
527
|
-
log_action('开始压缩', fpd_src ? ` ${fpd_src}` : '文件索引', fp_zip ? `${fp_zip}/${dirname || '{entries}'}` : '内存');
|
|
528
|
-
const { default: archiver } = await import('archiver');
|
|
529
|
-
let archive = archiver('zip');
|
|
530
|
-
let ostream = fp_zip ?
|
|
531
|
-
fs.createWriteStream(fp_zip, { highWaterMark: 16 * 2 ** 20 /* 16 MB */ })
|
|
532
|
-
:
|
|
533
|
-
new WritableMemoryStream();
|
|
534
|
-
const size = await new Promise(async (resolve, reject) => {
|
|
535
|
-
ostream.once('close', () => {
|
|
536
|
-
resolve(archive.pointer());
|
|
537
|
-
});
|
|
538
|
-
ostream.once('error', reject);
|
|
539
|
-
archive.once('error', reject);
|
|
540
|
-
archive.on('warning', error => {
|
|
541
|
-
console.log(error);
|
|
542
|
-
});
|
|
543
|
-
archive.pipe(ostream);
|
|
544
|
-
for (const fp in entries) {
|
|
545
|
-
const fdata = entries[fp];
|
|
546
|
-
if (fdata instanceof Uint8Array) {
|
|
547
|
-
if (print.files)
|
|
548
|
-
log_action('压缩', fdata.length.to_fsize_str(), fp);
|
|
549
|
-
archive.append(Buffer.isBuffer(fdata) ? fdata : Buffer.from(fdata.buffer), { name: fp });
|
|
550
|
-
}
|
|
551
|
-
else {
|
|
552
|
-
check(fp.isdir === fdata.isdir);
|
|
553
|
-
check(path.isAbsolute(fdata));
|
|
554
|
-
if (print.files)
|
|
555
|
-
log_action('压缩', fdata, fp);
|
|
556
|
-
if (fp.isdir)
|
|
557
|
-
archive.directory(fdata, fp);
|
|
558
|
-
else
|
|
559
|
-
archive.file(fdata, { name: fp });
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
await archive.finalize();
|
|
563
|
-
});
|
|
564
|
-
if (print.info)
|
|
565
|
-
console.log(`压缩完成,总大小 ${size.to_fsize_str()}`);
|
|
566
|
-
return fp_zip || ostream.pbuffer;
|
|
567
|
-
}
|
|
568
484
|
/** 解压 zip 包至文件夹,返回 fpd_out
|
|
569
485
|
- zip:
|
|
570
486
|
- 包路径 (string) 或
|
package/fzip.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface ZipOptions {
|
|
2
|
+
dirname?: string;
|
|
3
|
+
print?: {
|
|
4
|
+
info: boolean;
|
|
5
|
+
files: boolean;
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
/** 将文件夹或文件列表压缩为 zip,返回生成的压缩包路径 (fp_zip)
|
|
9
|
+
- data:
|
|
10
|
+
- fpd_src: 被压缩文件夹路径 (string) 或
|
|
11
|
+
- entries: 文件列表 (Record<压缩后相对路径, 原文件绝对路径 (string) | 数据 (Uint8Array)>)
|
|
12
|
+
- fp_zip: 生成的压缩包路径 (string)
|
|
13
|
+
- options?:
|
|
14
|
+
- dirname?: `fpd_src.fname` 传入 fpd_src 才生效,修改 zip 中顶层的文件夹的名字(需要以 / 结尾),如 'web/', 为空字符串时去掉顶层文件夹,不要多一个文件夹层级 (flat)
|
|
15
|
+
- print?:
|
|
16
|
+
- info?: `true` 开始压缩、压缩完成
|
|
17
|
+
- files?: `true` 打印压缩文件列表 */
|
|
18
|
+
export declare function fzip(data: string | Record<string, string | Uint8Array>, fp_zip: string, options?: ZipOptions): Promise<string>;
|
|
19
|
+
/** 将文件夹或文件列表压缩为 zip,返回压缩包数据 (Uint8Array)
|
|
20
|
+
- data:
|
|
21
|
+
- fpd_src: 被压缩文件夹路径 (string) 或
|
|
22
|
+
- entries: 文件列表 (Record<压缩后相对路径, 原文件绝对路径 (string) | 数据 (Uint8Array)>)
|
|
23
|
+
- options?:
|
|
24
|
+
- dirname?: `fpd_src.fname` 传入 fpd_src 才生效,修改 zip 中顶层的文件夹的名字(需要以 / 结尾),如 'web/', 为空字符串时去掉顶层文件夹,不要多一个文件夹层级 (flat)
|
|
25
|
+
- print?:
|
|
26
|
+
- info?: `true` 开始压缩、压缩完成
|
|
27
|
+
- files?: `true` 打印压缩文件列表 */
|
|
28
|
+
export declare function zip(data: string | Record<string, string | Uint8Array>, options?: ZipOptions): Promise<Buffer>;
|
package/fzip.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import { path } from "./path.js";
|
|
3
|
+
import { flist, log_action } from "./file.js";
|
|
4
|
+
import { noprint } from "./process.js";
|
|
5
|
+
import { WritableMemoryStream, check } from "./utils.js";
|
|
6
|
+
/** 将文件夹或文件列表压缩为 zip,返回生成的压缩包路径 (fp_zip)
|
|
7
|
+
- data:
|
|
8
|
+
- fpd_src: 被压缩文件夹路径 (string) 或
|
|
9
|
+
- entries: 文件列表 (Record<压缩后相对路径, 原文件绝对路径 (string) | 数据 (Uint8Array)>)
|
|
10
|
+
- fp_zip: 生成的压缩包路径 (string)
|
|
11
|
+
- options?:
|
|
12
|
+
- dirname?: `fpd_src.fname` 传入 fpd_src 才生效,修改 zip 中顶层的文件夹的名字(需要以 / 结尾),如 'web/', 为空字符串时去掉顶层文件夹,不要多一个文件夹层级 (flat)
|
|
13
|
+
- print?:
|
|
14
|
+
- info?: `true` 开始压缩、压缩完成
|
|
15
|
+
- files?: `true` 打印压缩文件列表 */
|
|
16
|
+
export async function fzip(data, fp_zip, options) {
|
|
17
|
+
return _zip(data, fp_zip, options);
|
|
18
|
+
}
|
|
19
|
+
/** 将文件夹或文件列表压缩为 zip,返回压缩包数据 (Uint8Array)
|
|
20
|
+
- data:
|
|
21
|
+
- fpd_src: 被压缩文件夹路径 (string) 或
|
|
22
|
+
- entries: 文件列表 (Record<压缩后相对路径, 原文件绝对路径 (string) | 数据 (Uint8Array)>)
|
|
23
|
+
- options?:
|
|
24
|
+
- dirname?: `fpd_src.fname` 传入 fpd_src 才生效,修改 zip 中顶层的文件夹的名字(需要以 / 结尾),如 'web/', 为空字符串时去掉顶层文件夹,不要多一个文件夹层级 (flat)
|
|
25
|
+
- print?:
|
|
26
|
+
- info?: `true` 开始压缩、压缩完成
|
|
27
|
+
- files?: `true` 打印压缩文件列表 */
|
|
28
|
+
export async function zip(data, options) {
|
|
29
|
+
return _zip(data, undefined, options);
|
|
30
|
+
}
|
|
31
|
+
async function _zip(data, fp_zip, { dirname, print = { files: true, info: true } } = {}) {
|
|
32
|
+
let entries;
|
|
33
|
+
let fpd_src;
|
|
34
|
+
if (typeof data === 'string') {
|
|
35
|
+
if (!path.isAbsolute(data) || !data.isdir)
|
|
36
|
+
throw new Error('fpd_src 必须是绝对路径且以 / 结尾');
|
|
37
|
+
fpd_src = data;
|
|
38
|
+
if (dirname === undefined)
|
|
39
|
+
dirname = fpd_src.fname;
|
|
40
|
+
if (!dirname.isdir)
|
|
41
|
+
throw new Error('dirname 需要以 / 结尾');
|
|
42
|
+
entries = Object.fromEntries((await flist(fpd_src, noprint))
|
|
43
|
+
.map(fp => ([dirname + fp, fpd_src + fp])));
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
check(!dirname, 'dirname 在传入 fpd_src 时才生效');
|
|
47
|
+
entries = data;
|
|
48
|
+
}
|
|
49
|
+
if (print.info)
|
|
50
|
+
log_action('开始压缩', fpd_src ? ` ${fpd_src}` : '文件索引', fp_zip ? `${fp_zip}/${dirname || '{entries}'}` : '内存');
|
|
51
|
+
const { default: archiver } = await import('archiver');
|
|
52
|
+
let archive = archiver('zip');
|
|
53
|
+
let ostream = fp_zip ?
|
|
54
|
+
fs.createWriteStream(fp_zip, { highWaterMark: 16 * 2 ** 20 /* 16 MB */ })
|
|
55
|
+
:
|
|
56
|
+
new WritableMemoryStream();
|
|
57
|
+
const size = await new Promise(async (resolve, reject) => {
|
|
58
|
+
ostream.once('close', () => {
|
|
59
|
+
resolve(archive.pointer());
|
|
60
|
+
});
|
|
61
|
+
ostream.once('error', reject);
|
|
62
|
+
archive.once('error', reject);
|
|
63
|
+
archive.on('warning', error => {
|
|
64
|
+
console.log(error);
|
|
65
|
+
});
|
|
66
|
+
archive.pipe(ostream);
|
|
67
|
+
for (const fp in entries) {
|
|
68
|
+
const fdata = entries[fp];
|
|
69
|
+
if (fdata instanceof Uint8Array) {
|
|
70
|
+
if (print.files)
|
|
71
|
+
log_action('压缩', fdata.length.to_fsize_str(), fp);
|
|
72
|
+
archive.append(Buffer.isBuffer(fdata) ? fdata : Buffer.from(fdata.buffer), { name: fp });
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
check(fp.isdir === fdata.isdir);
|
|
76
|
+
check(path.isAbsolute(fdata));
|
|
77
|
+
if (print.files)
|
|
78
|
+
log_action('压缩', fdata, fp);
|
|
79
|
+
if (fp.isdir)
|
|
80
|
+
archive.directory(fdata, fp);
|
|
81
|
+
else
|
|
82
|
+
archive.file(fdata, { name: fp });
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
await archive.finalize();
|
|
86
|
+
});
|
|
87
|
+
if (print.info)
|
|
88
|
+
console.log(`压缩完成,总大小 ${size.to_fsize_str()}`);
|
|
89
|
+
return fp_zip || ostream.pbuffer;
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=fzip.js.map
|
package/net.common.d.ts
CHANGED
|
@@ -100,6 +100,8 @@ export interface RemoteOptions {
|
|
|
100
100
|
/** 使用者自定义的在 websocket 连接出错时,或者 handlers 出错时的处理
|
|
101
101
|
用户设置后会覆盖默认的 print 错误功能 */
|
|
102
102
|
on_error?(error: WebSocketConnectionError | Error, remote: Remote): void;
|
|
103
|
+
/** 使用者自定义的,在重连之前调用的函数,比如可以修改 url,仅连接发起方有效 */
|
|
104
|
+
on_reconnect?(this: Remote): Promise<void>;
|
|
103
105
|
}
|
|
104
106
|
/** 通过创建 remote 对象对 websocket rpc 进行抽象
|
|
105
107
|
使用 remote.call() 进行一元 rpc
|
|
@@ -146,10 +148,11 @@ export declare class Remote {
|
|
|
146
148
|
error: WebSocketConnectionError | Error;
|
|
147
149
|
/** 作为 websocket 连接发起方,传入 url
|
|
148
150
|
作为 websocket 连接接收方,传入 websocket + name */
|
|
149
|
-
constructor({ name, url, websocket, funcs, print, verbose, probe, args, on_error, }?: RemoteOptions);
|
|
151
|
+
constructor({ name, url, websocket, funcs, print, verbose, probe, args, on_error, on_reconnect }?: RemoteOptions);
|
|
150
152
|
/** 统一处理首次连接和连接后的 websocket 错误 */
|
|
151
153
|
_on_error: (error: WebSocketConnectionError | Error) => void;
|
|
152
|
-
|
|
154
|
+
on_reconnect?: (this: Remote) => Promise<void>;
|
|
155
|
+
reconnect: () => Promise<void>;
|
|
153
156
|
_on_message: (data: ArrayBuffer) => void;
|
|
154
157
|
/** 使用者自定义的在 websocket 连接出错时,或者 handlers 出错时的处理
|
|
155
158
|
用户设置后会覆盖默认的 print 错误功能 */
|
package/net.common.js
CHANGED
|
@@ -238,12 +238,14 @@ export class Remote {
|
|
|
238
238
|
error;
|
|
239
239
|
/** 作为 websocket 连接发起方,传入 url
|
|
240
240
|
作为 websocket 连接接收方,传入 websocket + name */
|
|
241
|
-
constructor({ name, url, websocket, funcs, print, verbose, probe, args, on_error, } = {}) {
|
|
241
|
+
constructor({ name, url, websocket, funcs, print, verbose, probe, args, on_error, on_reconnect } = {}) {
|
|
242
242
|
if (name)
|
|
243
243
|
this.name = name;
|
|
244
244
|
if (url) {
|
|
245
245
|
check(!websocket, '构建 Remote 时 url 和 websocket 只能传其中一个');
|
|
246
246
|
this.url = url;
|
|
247
|
+
if (on_reconnect)
|
|
248
|
+
this.on_reconnect = on_reconnect;
|
|
247
249
|
}
|
|
248
250
|
else { // 连接接收方,一定是 nodejs 环境
|
|
249
251
|
check(websocket, '构建 Remote 时需传入 url 或者 websocket');
|
|
@@ -313,8 +315,11 @@ export class Remote {
|
|
|
313
315
|
}
|
|
314
316
|
this.on_error(error, this);
|
|
315
317
|
};
|
|
316
|
-
|
|
318
|
+
on_reconnect;
|
|
319
|
+
reconnect = async () => {
|
|
317
320
|
this.reconnecting = null;
|
|
321
|
+
if (this.on_reconnect)
|
|
322
|
+
await this.on_reconnect();
|
|
318
323
|
this.try_connect();
|
|
319
324
|
};
|
|
320
325
|
_on_message = (data) => {
|