xshell 1.0.79 → 1.0.81
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 +14 -11
- package/file.js +29 -3
- package/i18n/dict.json +3 -0
- package/net.js +17 -8
- package/package.json +8 -8
- package/process.d.ts +10 -0
- package/server.js +6 -2
package/file.d.ts
CHANGED
|
@@ -179,23 +179,26 @@ export interface ZipOptions {
|
|
|
179
179
|
files: boolean;
|
|
180
180
|
};
|
|
181
181
|
}
|
|
182
|
-
/**
|
|
183
|
-
返回 fp_zip 或压缩包数据
|
|
182
|
+
/** 将文件夹或文件列表压缩为 zip,返回生成的压缩包路径 (fp_zip)
|
|
184
183
|
- data:
|
|
185
|
-
- 被压缩文件夹路径 (
|
|
186
|
-
-
|
|
187
|
-
- fp_zip
|
|
188
|
-
- 传压缩包完整路径时压缩到文件, 函数返回值为 Promise<zip 路径>
|
|
189
|
-
- 传 undefined 时压缩到内存, 函数返回值为 Promise<zip Uint8Array>
|
|
184
|
+
- fpd_src: 被压缩文件夹路径 (string) 或
|
|
185
|
+
- entries: 文件列表 (Record<压缩后相对路径, 原文件绝对路径 (string) | 数据 (Uint8Array)>)
|
|
186
|
+
- fp_zip: 生成的压缩包路径 (string)
|
|
190
187
|
- options?:
|
|
191
188
|
- dirname?: `fpd_src.fname` 传入 fpd_src 才生效,修改 zip 中顶层的文件夹的名字(需要以 / 结尾),如 'web/', 为空字符串时去掉顶层文件夹,不要多一个文件夹层级 (flat)
|
|
192
189
|
- print?:
|
|
193
190
|
- info?: `true` 开始压缩、压缩完成
|
|
194
191
|
- files?: `true` 打印压缩文件列表 */
|
|
195
|
-
export declare function fzip(
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
192
|
+
export declare function fzip(data: string | Record<string, string | Uint8Array>, fp_zip: string, options?: ZipOptions): Promise<string>;
|
|
193
|
+
/** 将文件夹或文件列表压缩为 zip,返回压缩包数据 (Uint8Array)
|
|
194
|
+
- data:
|
|
195
|
+
- fpd_src: 被压缩文件夹路径 (string) 或
|
|
196
|
+
- entries: 文件列表 (Record<压缩后相对路径, 原文件绝对路径 (string) | 数据 (Uint8Array)>)
|
|
197
|
+
- options?:
|
|
198
|
+
- print?:
|
|
199
|
+
- info?: `true` 开始压缩、压缩完成
|
|
200
|
+
- files?: `true` 打印压缩文件列表 */
|
|
201
|
+
export declare function zip(data: string | Record<string, string | Uint8Array>, options?: ZipOptions): Promise<Buffer>;
|
|
199
202
|
export declare let fwatchers: Record<string, fs.FSWatcher>;
|
|
200
203
|
/** 跟踪文本文件追加的内容,类似 tail -f */
|
|
201
204
|
export declare function ftail(fp: string, handler: (lines: string[]) => void | Promise<void>, { print }?: {
|
package/file.js
CHANGED
|
@@ -362,7 +362,31 @@ export async function flink(fp_real, fp_link, { junction = false, print = true }
|
|
|
362
362
|
else
|
|
363
363
|
fsp.symlink(fp_real, fp_link, is_fpd_real ? 'dir' : 'file');
|
|
364
364
|
}
|
|
365
|
-
|
|
365
|
+
/** 将文件夹或文件列表压缩为 zip,返回生成的压缩包路径 (fp_zip)
|
|
366
|
+
- data:
|
|
367
|
+
- fpd_src: 被压缩文件夹路径 (string) 或
|
|
368
|
+
- entries: 文件列表 (Record<压缩后相对路径, 原文件绝对路径 (string) | 数据 (Uint8Array)>)
|
|
369
|
+
- fp_zip: 生成的压缩包路径 (string)
|
|
370
|
+
- options?:
|
|
371
|
+
- dirname?: `fpd_src.fname` 传入 fpd_src 才生效,修改 zip 中顶层的文件夹的名字(需要以 / 结尾),如 'web/', 为空字符串时去掉顶层文件夹,不要多一个文件夹层级 (flat)
|
|
372
|
+
- print?:
|
|
373
|
+
- info?: `true` 开始压缩、压缩完成
|
|
374
|
+
- files?: `true` 打印压缩文件列表 */
|
|
375
|
+
export async function fzip(data, fp_zip, options) {
|
|
376
|
+
return _zip(data, fp_zip, options);
|
|
377
|
+
}
|
|
378
|
+
/** 将文件夹或文件列表压缩为 zip,返回压缩包数据 (Uint8Array)
|
|
379
|
+
- data:
|
|
380
|
+
- fpd_src: 被压缩文件夹路径 (string) 或
|
|
381
|
+
- entries: 文件列表 (Record<压缩后相对路径, 原文件绝对路径 (string) | 数据 (Uint8Array)>)
|
|
382
|
+
- options?:
|
|
383
|
+
- print?:
|
|
384
|
+
- info?: `true` 开始压缩、压缩完成
|
|
385
|
+
- files?: `true` 打印压缩文件列表 */
|
|
386
|
+
export async function zip(data, options) {
|
|
387
|
+
return _zip(data, undefined, options);
|
|
388
|
+
}
|
|
389
|
+
async function _zip(data, fp_zip, { dirname, print = { files: true, info: true } } = {}) {
|
|
366
390
|
let entries;
|
|
367
391
|
let fpd_src;
|
|
368
392
|
if (typeof data === 'string') {
|
|
@@ -376,12 +400,14 @@ export async function fzip(data, fp_zip, { dirname, print = { files: true, info:
|
|
|
376
400
|
entries = Object.fromEntries((await flist(fpd_src, { print: false }))
|
|
377
401
|
.map(fp => ([dirname + fp, fpd_src + fp])));
|
|
378
402
|
}
|
|
379
|
-
else
|
|
403
|
+
else {
|
|
404
|
+
assert(!dirname, 'dirname 在传入 fpd_src 时才生效');
|
|
380
405
|
entries = data;
|
|
406
|
+
}
|
|
381
407
|
if (print.info)
|
|
382
408
|
console.log(`开始压缩${fpd_src ? ` ${fpd_src}` : '文件索引'} -> ${fp_zip ? `${fp_zip}/${dirname || '{entries}'}` : '内存'}`);
|
|
383
409
|
const { default: archiver } = await import('archiver');
|
|
384
|
-
let archive = archiver('zip'
|
|
410
|
+
let archive = archiver('zip');
|
|
385
411
|
let ostream = fp_zip ?
|
|
386
412
|
fs.createWriteStream(fp_zip, { highWaterMark: 16 * 2 ** 20 /* 16 MB */ })
|
|
387
413
|
:
|
package/i18n/dict.json
CHANGED
|
@@ -376,5 +376,8 @@
|
|
|
376
376
|
},
|
|
377
377
|
"不支持 content-encoding: {{encoding}} 的 http 请求": {
|
|
378
378
|
"en": "http requests with content-encoding: {{encoding}} are not supported"
|
|
379
|
+
},
|
|
380
|
+
"等待 {{duration}} 秒后重试 request (已尝试 {{_count}} 次) …": {
|
|
381
|
+
"en": "Wait {{duration}} seconds before retrying request (tried {{_count}} times) …"
|
|
379
382
|
}
|
|
380
383
|
}
|
package/net.js
CHANGED
|
@@ -43,15 +43,18 @@ async function request_retry(url, options, timeout, retries = 0, count = 0) {
|
|
|
43
43
|
return await undici_request(url, options);
|
|
44
44
|
}
|
|
45
45
|
catch (error) {
|
|
46
|
-
if (
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
46
|
+
if (error.name === 'TimeoutError') {
|
|
47
|
+
if (count < retries) {
|
|
48
|
+
const duration = 2 ** count;
|
|
49
|
+
console.log(`${t('等待 {{duration}} 秒后重试 request (已尝试 {{_count}} 次) …', { duration, _count: count + 1 }).yellow} ${url.toString().blue.underline}`);
|
|
50
|
+
await delay(1000 * duration);
|
|
51
|
+
return request_retry(url, options, timeout, retries, count + 1);
|
|
52
|
+
}
|
|
53
|
+
else
|
|
54
|
+
throw Object.assign(new Error(`request 超时: ${url.toString()}`), { name: 'TimeoutError' });
|
|
54
55
|
}
|
|
56
|
+
else
|
|
57
|
+
throw error;
|
|
55
58
|
}
|
|
56
59
|
}
|
|
57
60
|
export async function request(url, options = {}) {
|
|
@@ -118,6 +121,12 @@ export async function request(url, options = {}) {
|
|
|
118
121
|
})(),
|
|
119
122
|
// todo: 强制手动处理重定向,来正确处理 cookie ?
|
|
120
123
|
maxRedirections: redirect === 'follow' ? 5 : 0,
|
|
124
|
+
// 下面这些 timeout 都不是总的时间,没法用
|
|
125
|
+
// headersTimeout: timeout - 1000,
|
|
126
|
+
// 从收完 headers 开始算
|
|
127
|
+
// bodyTimeout: timeout - 1000,
|
|
128
|
+
// @ts-ignore 没有类型声明,实际可用
|
|
129
|
+
// connectTimeout: timeout - 1000,
|
|
121
130
|
headers,
|
|
122
131
|
// --- body
|
|
123
132
|
body: (() => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xshell",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.81",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"bin": {
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"emoji-regex": "^10.3.0",
|
|
71
71
|
"gulp-sort": "^2.0.0",
|
|
72
72
|
"hash-string": "^1.0.0",
|
|
73
|
-
"i18next": "^23.7.
|
|
73
|
+
"i18next": "^23.7.16",
|
|
74
74
|
"i18next-scanner": "^4.4.0",
|
|
75
75
|
"js-cookie": "^3.0.5",
|
|
76
76
|
"koa": "^2.15.0",
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
"tslib": "^2.6.2",
|
|
90
90
|
"typescript": "^5.3.3",
|
|
91
91
|
"ua-parser-js": "2.0.0-alpha.2",
|
|
92
|
-
"undici": "^6.
|
|
92
|
+
"undici": "^6.3.0",
|
|
93
93
|
"vinyl": "^3.0.0",
|
|
94
94
|
"vinyl-fs": "^4.0.0",
|
|
95
95
|
"ws": "^8.16.0",
|
|
@@ -107,19 +107,19 @@
|
|
|
107
107
|
"@types/chardet": "^0.8.3",
|
|
108
108
|
"@types/gulp-sort": "2.0.4",
|
|
109
109
|
"@types/js-cookie": "^3.0.6",
|
|
110
|
-
"@types/koa": "^2.
|
|
110
|
+
"@types/koa": "^2.14.0",
|
|
111
111
|
"@types/koa-compress": "^4.0.6",
|
|
112
112
|
"@types/lodash": "^4.14.202",
|
|
113
113
|
"@types/mime-types": "^2.1.4",
|
|
114
|
-
"@types/node": "^20.10.
|
|
115
|
-
"@types/react": "^18.2.
|
|
114
|
+
"@types/node": "^20.10.8",
|
|
115
|
+
"@types/react": "^18.2.47",
|
|
116
116
|
"@types/through2": "^2.0.41",
|
|
117
117
|
"@types/tough-cookie": "^4.0.5",
|
|
118
118
|
"@types/ua-parser-js": "^0.7.39",
|
|
119
119
|
"@types/vinyl-fs": "^3.0.5",
|
|
120
120
|
"@types/vscode": "^1.85.0",
|
|
121
|
-
"@typescript-eslint/eslint-plugin": "^6.
|
|
122
|
-
"@typescript-eslint/parser": "^6.
|
|
121
|
+
"@typescript-eslint/eslint-plugin": "^6.18.1",
|
|
122
|
+
"@typescript-eslint/parser": "^6.18.1",
|
|
123
123
|
"eslint": "^8.56.0",
|
|
124
124
|
"eslint-plugin-react": "^7.33.2",
|
|
125
125
|
"eslint-plugin-xlint": "^1.0.11"
|
package/process.d.ts
CHANGED
|
@@ -65,6 +65,16 @@ export interface CallResult<TOutput extends string | Buffer = string> {
|
|
|
65
65
|
child: ChildProcess;
|
|
66
66
|
[inspect.custom](): string;
|
|
67
67
|
}
|
|
68
|
+
export interface CallError {
|
|
69
|
+
result: {
|
|
70
|
+
pid: number;
|
|
71
|
+
stdout: string;
|
|
72
|
+
stderr: string;
|
|
73
|
+
code: number;
|
|
74
|
+
signal: number | NodeJS.Signals;
|
|
75
|
+
child: ChildProcess;
|
|
76
|
+
};
|
|
77
|
+
}
|
|
68
78
|
/** call process for result
|
|
69
79
|
- exe: .exe 路径或文件名 (建议使用路径,跳过 path 搜索,性能更高) path or filename (full path is recommanded to skip path searching for better perf)
|
|
70
80
|
- args: `[]` 参数列表 arguments list
|
package/server.js
CHANGED
|
@@ -109,18 +109,22 @@ export class Server {
|
|
|
109
109
|
// fpd_certs 文件夹下面的每个 .key 对应一个证书及域名
|
|
110
110
|
(await flist(fpd_certs, { print: false, filter: /\.key$/ }))
|
|
111
111
|
.map(async (fname) => {
|
|
112
|
-
|
|
112
|
+
let domain = fname.slice(0, -'.key'.length);
|
|
113
113
|
const [key, cert] = await Promise.all([
|
|
114
114
|
fname,
|
|
115
115
|
`${domain}.crt`,
|
|
116
116
|
].map(async (fname) => fread(`${fpd_certs}${fname}`, { print: false })));
|
|
117
|
+
if (domain.startsWith('star.'))
|
|
118
|
+
domain = `*.${domain.slice('star.'.length)}`;
|
|
117
119
|
return [domain, { key, cert }];
|
|
118
120
|
})));
|
|
119
121
|
const default_ctx = lazy_secure_ctxs[this.default_hostnames.find(hostname => hostname in lazy_secure_ctxs)];
|
|
120
122
|
assert(default_ctx);
|
|
121
123
|
this.http2_server = http2_create_server({
|
|
122
124
|
SNICallback(servername, callback) {
|
|
123
|
-
let lazy_ctx = lazy_secure_ctxs[servername] ||
|
|
125
|
+
let lazy_ctx = lazy_secure_ctxs[servername] ||
|
|
126
|
+
lazy_secure_ctxs[servername.replace(/^.*?\./, '*.')] ||
|
|
127
|
+
default_ctx;
|
|
124
128
|
callback(null, lazy_ctx.ctx ??= createSecureContext(lazy_ctx));
|
|
125
129
|
},
|
|
126
130
|
allowHTTP1: true,
|