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 CHANGED
@@ -179,23 +179,26 @@ export interface ZipOptions {
179
179
  files: boolean;
180
180
  };
181
181
  }
182
- /** 将文件夹压缩为 zip
183
- 返回 fp_zip 或压缩包数据
182
+ /** 将文件夹或文件列表压缩为 zip,返回生成的压缩包路径 (fp_zip)
184
183
  - data:
185
- - 被压缩文件夹路径 (fpd_src: string) 或
186
- - 文件索引对象 (entries: Record<压缩后相对路径, 原文件绝对路径 (string) | 数据 (Uint8Array)>)
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(entries: Record<string, string | Uint8Array>, fp_zip?: undefined, options?: ZipOptions): Promise<Uint8Array>;
196
- export declare function fzip(entries: Record<string, string | Uint8Array>, fp_zip: string, options?: ZipOptions): Promise<string>;
197
- export declare function fzip(fpd_src: string, fp_zip?: undefined, options?: ZipOptions): Promise<Uint8Array>;
198
- export declare function fzip(fpd_src: string, fp_zip: string, options?: ZipOptions): Promise<string>;
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
- export async function fzip(data, fp_zip, { dirname, print = { files: true, info: true } } = {}) {
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', { zlib: { chunkSize: 16 * 2 ** 20 /* 16 MB */ } });
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 (count >= retries ||
47
- error.name !== 'TimeoutError' && !['ECONNRESET', 'ETIMEDOUT', 'ESOCKETTIMEDOUT'].includes(error.cause?.code))
48
- throw error;
49
- else {
50
- const duration = 2 ** count;
51
- console.log(`${t('等待 {{duration}} 秒后重试 fetch ({{_count}}) …', { duration, _count: count }).yellow} ${url.toString().blue.underline}`);
52
- await delay(1000 * duration);
53
- return request_retry(url, options, timeout, retries, count + 1);
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.79",
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.13",
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.2.1",
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.13.12",
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.6",
115
- "@types/react": "^18.2.46",
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.17.0",
122
- "@typescript-eslint/parser": "^6.17.0",
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
- const domain = fname.slice(0, -'.key'.length);
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] || default_ctx;
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,