xshell 1.3.49 → 1.3.50

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
@@ -259,10 +259,6 @@ export declare function funzip(zip: string | Uint8Array | ArrayBuffer, fpd_out:
259
259
  - filter?: 用于过滤要解压的文件, 返回 falsy 值时忽略这个文件,要注意 file.name 为完整的相对路径(没有 strip) */
260
260
  export declare function unzip(zip: string | Uint8Array | ArrayBuffer, options?: UnzipOptions): Promise<Record<string, Uint8Array>>;
261
261
  export declare let fwatchers: Record<string, fs.FSWatcher>;
262
- /** 跟踪文本文件追加的内容,类似 tail -f */
263
- export declare function ftail(fp: string, handler: (lines: string[]) => void | Promise<void>, { print }?: {
264
- print?: boolean;
265
- }): Promise<fs.FSWatcher>;
266
262
  /** 打开一个文件并搜索替换某个 pattern */
267
263
  export declare function freplace(fp: string, pattern: string | RegExp, replacement: string | ((substring: string, ...args: any[]) => string), { print }?: {
268
264
  print?: 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, url_width, throttle, decode, strcmp } from "./utils.js";
7
+ import { check, url_width, 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'];
@@ -699,52 +699,6 @@ const ftrashes = new Set([
699
699
  'yarn.lock',
700
700
  ].map(f => f.toLowerCase()));
701
701
  export let fwatchers = {};
702
- /** 跟踪文本文件追加的内容,类似 tail -f */
703
- export async function ftail(fp, handler, { print = true } = {}) {
704
- fwatchers[fp]?.close();
705
- const { size } = await fstat(fp);
706
- let pointer = Number(size);
707
- let lock = new Lock(await fopen(fp));
708
- let fbuf = Buffer.allocUnsafe(2 ** 20);
709
- let strbuf = '';
710
- let decoder = new TextDecoder();
711
- if (print)
712
- console.log('开始跟踪追加内容', fp);
713
- const onchange_throttled = throttle(250, async () => {
714
- if (lock.locked)
715
- return;
716
- await lock.request(async (handle) => {
717
- const { bytesRead } = await handle.read(fbuf, 0, fbuf.length, pointer);
718
- pointer += bytesRead;
719
- const chunk = decoder.decode(fbuf.subarray(0, bytesRead), { stream: true });
720
- let lines = [];
721
- let j = 0;
722
- for (let i = 0; (i = chunk.indexOf('\n', j)) >= 0;) {
723
- let line = chunk.slice(j, i);
724
- if (strbuf) {
725
- line = strbuf + line;
726
- strbuf = '';
727
- }
728
- j = i + 1;
729
- lines.push(line);
730
- }
731
- strbuf = chunk.slice(j);
732
- await handler(lines);
733
- });
734
- });
735
- let watcher = fs.watch(fp, event => {
736
- if (event === 'change')
737
- onchange_throttled();
738
- else {
739
- console.error(`被监听的文件 ${fp.quote()} 出现了 rename 事件,结束 ftail`);
740
- watcher.close();
741
- }
742
- });
743
- watcher.on('error', error => {
744
- console.error(error);
745
- });
746
- return fwatchers[fp] = watcher;
747
- }
748
702
  /** 打开一个文件并搜索替换某个 pattern */
749
703
  export async function freplace(fp, pattern, replacement, { print = true } = {}) {
750
704
  await fwrite(fp, (await fread(fp, noprint))
package/net.d.ts CHANGED
@@ -37,7 +37,7 @@ export interface RequestOptions {
37
37
  queries?: Record<string, any>;
38
38
  headers?: Record<string, string>;
39
39
  body?: string | Record<string, any> | Uint8Array | URLSearchParams | Readable;
40
- type?: 'application/json' | 'application/x-www-form-urlencoded' | 'multipart/form-data';
40
+ type?: 'application/json' | 'application/x-www-form-urlencoded' | 'multipart/form-data' | 'application/jose+json';
41
41
  proxy?: boolean | ValueOf<typeof MyProxy> | string;
42
42
  encoding?: Encoding | 'binary';
43
43
  retries?: true | number;
@@ -46,6 +46,9 @@ export interface RequestOptions {
46
46
  cookies?: Record<string, string>;
47
47
  redirect?: 'follow' | 'manual';
48
48
  decode?: boolean;
49
+ dryrun?: boolean;
50
+ browser?: boolean;
51
+ ua?: string;
49
52
  print?: {
50
53
  retry: boolean;
51
54
  timeout: boolean;
@@ -96,6 +99,9 @@ export declare class StatusCodeError extends Error {
96
99
  - raw?: `false` 传入后返回整个 response (RawResponse),body 为 Readable
97
100
  - full?: `false` 传入后返回整个 response (FullResponse),body 根据 encoding 对应为 string 或 Buffer
98
101
  - decode?: `true` 根据 content-encoding: br 等解码压缩后的 response.body
102
+ - browser?: `false` 使用 chrome 浏览器的 ua
103
+ - ua?: `无 user-agent 头` 快捷设置 user-agent 头,默认不发送
104
+ - dryrun?: `false` 仅打印 undici options, 并不实际发送请求,返回 undefined
99
105
  - print?:
100
106
  - retry: `true` 是否打印 "等待 1 秒后重试 request" 提示信息
101
107
  - timeout: `true` 是否打印最后一次超时重试失败时的错误 */
package/net.js CHANGED
@@ -67,7 +67,7 @@ export async function request(url, options = {}) {
67
67
  undici ??= (await import('undici')).default;
68
68
  const { Cookie } = await import('tough-cookie');
69
69
  await cookies.init();
70
- const { queries, headers: _headers, body, type = 'application/json', timeout = 5 * 1000, auth, cookies: _cookies, raw = false, full = false, redirect = 'follow', decode = true, print = {
70
+ const { queries, headers: _headers, body, type = 'application/json', timeout = 5 * 1000, auth, cookies: _cookies, raw = false, full = false, redirect = 'follow', decode = true, dryrun, ua, browser: browser_ua, print = {
71
71
  timeout: true,
72
72
  retry: true
73
73
  } } = options;
@@ -87,11 +87,16 @@ export async function request(url, options = {}) {
87
87
  retries = 2;
88
88
  // --- headers, http/2 开始都用小写的 headers
89
89
  let headers = {
90
- 'accept-language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,ja-JP;q=0.6,ja;q=0.5',
91
- 'accept-encoding': 'gzip, deflate, br',
92
- 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36',
93
- 'sec-ch-ua-platform': '"Windows"',
94
- 'sec-ch-ua-platform-version': '"19.0.0"',
90
+ 'accept-language': 'zh-CN,zh;q=0.9',
91
+ 'accept-encoding': 'gzip, deflate, br, zstd',
92
+ ...browser_ua ? {
93
+ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36',
94
+ 'sec-ch-ua-platform': '"Windows"',
95
+ 'sec-ch-ua-platform-version': '"19.0.0"'
96
+ } : {},
97
+ ...ua ? {
98
+ 'user-agent': ua
99
+ } : {}
95
100
  };
96
101
  // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest_API/Using_FormData_Objects
97
102
  // When using FormData to submit POST requests using XMLHttpRequest or the Fetch API with the multipart/form-data content type (e.g., when uploading files and blobs to the server),
@@ -137,6 +142,10 @@ export async function request(url, options = {}) {
137
142
  headers,
138
143
  body: get_request_body(body, type)
139
144
  };
145
+ if (dryrun) {
146
+ console.log(undici_options);
147
+ return;
148
+ }
140
149
  let response;
141
150
  try {
142
151
  const { statusCode: status, headers: _headers, body: _body } = await request_retry(url, undici_options, timeout, retries, 0, print);
@@ -253,7 +262,7 @@ function get_request_body(body, type) {
253
262
  return undefined;
254
263
  if (typeof body?.read === 'function' && isReadable(body))
255
264
  return body;
256
- if (type === 'application/json') {
265
+ if (type === 'application/json' || type === 'application/jose+json') {
257
266
  // 可能的类型 string | Record<string, any> | Uint8Array
258
267
  if (typeof body === 'string')
259
268
  return encode(body);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xshell",
3
- "version": "1.3.49",
3
+ "version": "1.3.50",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "bin": {
@@ -69,13 +69,13 @@
69
69
  "https-proxy-agent": "^8.0.0",
70
70
  "i18next": "25.8.1",
71
71
  "i18next-scanner": "^4.6.0",
72
- "koa": "^3.1.2",
72
+ "koa": "^3.2.0",
73
73
  "koa-compress": "^5.2.1",
74
74
  "license-webpack-plugin": "^4.0.2",
75
75
  "mime-types": "^3.0.2",
76
76
  "p-map": "^7.0.4",
77
77
  "react": "^19.2.4",
78
- "react-i18next": "^16.6.2",
78
+ "react-i18next": "^17.0.1",
79
79
  "resolve-path": "^1.4.0",
80
80
  "sass": "^1.98.0",
81
81
  "sass-loader": "^16.0.7",
@@ -86,9 +86,9 @@
86
86
  "ts-loader": "^9.5.4",
87
87
  "tslib": "^2.8.1",
88
88
  "typescript": "^6.0.2",
89
- "undici": "^7.24.5",
89
+ "undici": "^7.24.6",
90
90
  "webpack": "^5.105.4",
91
- "webpack-bundle-analyzer": "^5.2.0",
91
+ "webpack-bundle-analyzer": "^5.3.0",
92
92
  "ws": "^8.20.0"
93
93
  },
94
94
  "devDependencies": {
package/path.d.ts CHANGED
@@ -54,7 +54,7 @@ export declare function extname(path: string): string;
54
54
  /** `/` */
55
55
  export declare const sep = "/";
56
56
  /** The platform-specific file delimiter. ';' or ':'. */
57
- export declare const delimiter: ":" | ";";
57
+ export declare const delimiter: ";" | ":";
58
58
  /** Returns an object from a path string - the opposite of format().
59
59
  @param path path to evaluate.
60
60
  @throws {TypeError} if `path` is not a string. */
@@ -81,7 +81,7 @@ export declare let path: {
81
81
  basename: typeof basename;
82
82
  extname: typeof extname;
83
83
  sep: string;
84
- delimiter: ":" | ";";
84
+ delimiter: ";" | ":";
85
85
  parse: typeof parse;
86
86
  format: typeof format;
87
87
  toNamespacedPath: typeof toNamespacedPath;
package/utils.common.d.ts CHANGED
@@ -82,6 +82,9 @@ export declare function timeout<TReturn>(milliseconds: number, action: Promise<T
82
82
  action 返回 trusy 值时认为成功,返回 action 的结果
83
83
  如果次数用尽仍然失败,返回 null */
84
84
  export declare function poll<TResult>(duration: number, times: number, action: (breaker: () => void) => Promise<TResult>): Promise<TResult>;
85
+ export declare const one_day: number;
86
+ /** 获取到下一次 hour:minute 时钟所需 delay 的毫秒数 */
87
+ export declare function get_delay_to_clock(hour: number, minute?: number): number;
85
88
  /** 每天在固定时间执行操作
86
89
  - hour: 0 - 23 之间的整数,在这个点执行
87
90
  - action */
@@ -176,7 +179,10 @@ export declare function grep(str: string, pattern: string | RegExp): string;
176
179
  export declare function lowercase_first_letter(str: string): string;
177
180
  /** 大于 n 的最小的 2 的幂次 */
178
181
  export declare function ceil2(n: number): number;
179
- /** 节流,最多只在时间间隔末尾调用一次,可以设置首次调用是否延后 */
182
+ /** 节流,最多只在时间间隔末尾调用一次,可以设置首次调用是否延后
183
+ - duration
184
+ - func
185
+ - delay_first?: `false` */
180
186
  export declare function throttle(duration: number, func: Function, delay_first?: boolean): (this: any, ...args: any[]) => void;
181
187
  /** 防抖,间隔一段时间不再触发时调用,同时大幅优化减少 setTimeout, clearTimeout 的调用次数 */
182
188
  export declare function debounce(duration: number, func: Function): (this: any, ...args: any[]) => void;
package/utils.common.js CHANGED
@@ -255,18 +255,24 @@ export async function poll(duration, times, action) {
255
255
  }
256
256
  return null;
257
257
  }
258
+ export const one_day = 1000 * 60 * 60 * 24;
259
+ /** 获取到下一次 hour:minute 时钟所需 delay 的毫秒数 */
260
+ export function get_delay_to_clock(hour, minute = 0) {
261
+ const now = Date.now();
262
+ let today = new Date(now);
263
+ today.setHours(hour, minute, 0, 0);
264
+ let target = today.getTime();
265
+ // 如果目标时间已过,则设置为明天的目标时间
266
+ if (target <= now)
267
+ target += one_day;
268
+ return target - now;
269
+ }
258
270
  /** 每天在固定时间执行操作
259
271
  - hour: 0 - 23 之间的整数,在这个点执行
260
272
  - action */
261
273
  export async function schedule_everyday(hour, minute, action) {
262
- const now = Date.now();
263
- let target = new Date();
264
- target.setHours(hour, minute, 0, 0);
265
- // 如果目标时间已过,设定为明天的时间
266
- if (now > target.getTime())
267
- target.setDate(target.getDate() + 1);
268
274
  // 等时间到
269
- await delay(target.getTime() - now);
275
+ await delay(get_delay_to_clock(hour, minute));
270
276
  for (;;) {
271
277
  try {
272
278
  await action();
@@ -276,7 +282,7 @@ export async function schedule_everyday(hour, minute, action) {
276
282
  console.error(error);
277
283
  }
278
284
  // 等一天
279
- await delay(1000 * 60 * 60 * 24);
285
+ await delay(one_day);
280
286
  }
281
287
  }
282
288
  /** 模糊过滤字符串列表或对象列表,常用于根据用户输入补全或搜索过滤
@@ -534,7 +540,10 @@ export function ceil2(n) {
534
540
  ;
535
541
  return power;
536
542
  }
537
- /** 节流,最多只在时间间隔末尾调用一次,可以设置首次调用是否延后 */
543
+ /** 节流,最多只在时间间隔末尾调用一次,可以设置首次调用是否延后
544
+ - duration
545
+ - func
546
+ - delay_first?: `false` */
538
547
  export function throttle(duration, func, delay_first = false) {
539
548
  let timeout = 0;
540
549
  let last = 0;