xshell 1.0.95 → 1.0.96

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/Terminal.js CHANGED
@@ -51,8 +51,11 @@ class TerminalModel extends Model {
51
51
  async subscribe_stdio(remote) {
52
52
  assert(!this.stdio_id);
53
53
  const id = this.stdio_id = genid();
54
- remote.handlers.set(id, ({ data: [chunk] }) => {
55
- this.term.write(chunk);
54
+ remote.handlers.set(id, ({ data, error }) => {
55
+ if (error)
56
+ throw error;
57
+ else
58
+ this.term.write(data[0]);
56
59
  });
57
60
  await remote.send({ id, func: 'subscribe_stdio' });
58
61
  }
package/apps.d.ts CHANGED
@@ -6,9 +6,9 @@ export declare let npm: {
6
6
  bin: string;
7
7
  call(cwd: string, bin: string, args: string[], options?: CallOptions): Promise<import("./process.js").CallResult<string>>;
8
8
  /** node.exe E:/sdk/nodejs/node_modules/corepack/dist/pnpm.js install
9
- - cwd?: `fpd_root`
9
+ - cwd
10
10
  - pkgs?: `[ ]` */
11
- install(cwd?: string, pkgs?: string[], { save_dev, save_peer, legacy, force, term, inspect, break: _break, }?: {
11
+ install(cwd: string, pkgs?: string[], { save_dev, save_peer, legacy, force, term, inspect, break: _break, }?: {
12
12
  save_dev?: boolean;
13
13
  save_peer?: boolean;
14
14
  legacy?: boolean;
package/apps.js CHANGED
@@ -1,14 +1,14 @@
1
1
  import util from 'util';
2
- import { call_nodejs, exe_nodejs, platform } from './process.js';
2
+ import { call_nodejs, platform, username } from './process.js';
3
3
  import { assert } from './utils.js';
4
4
  import { path } from './path.js';
5
5
  export let npm = {
6
- bin: `${platform === 'win32' ? exe_nodejs.fdir : '/usr/lib/'}node_modules/corepack/dist/pnpm.js`,
6
+ bin: platform == 'win32' ? `C:/Users/${username}/AppData/Roaming/npm/node_modules/pnpm/bin/pnpm.cjs` : '/usr/bin/pnpm',
7
7
  async call(cwd, bin, args, options) {
8
8
  return call_nodejs(bin, args, { cwd, ...options });
9
9
  },
10
10
  /** node.exe E:/sdk/nodejs/node_modules/corepack/dist/pnpm.js install
11
- - cwd?: `fpd_root`
11
+ - cwd
12
12
  - pkgs?: `[ ]` */
13
13
  async install(cwd, pkgs = [], { save_dev = false, save_peer = false, legacy = false, force = false, term = false, inspect = false, break: _break = false, } = {}) {
14
14
  const args = [
package/net.d.ts CHANGED
@@ -91,8 +91,9 @@ export interface RequestError extends Error {
91
91
  - 为非空 string 作为代理地址
92
92
  - 为 falsy 值时设为 false
93
93
  - encoding?: `根据网页 content-type: charset=gb18030 提取 || 'utf-8'` 传入 'binary' 时返回 Buffer
94
+ (只对非 raw 的请求起作用)
94
95
  - retries?: `false` 可以传入 true (默认 2 次) 或 重试次数
95
- - timeout?: `5 * 1000`
96
+ - timeout?: `5 * 1000` 超时后会抛出 error.name 为 'TimeoutError' 的 error, 可以传入 0 来禁用超时
96
97
  - auth?: BasicAuth | BearerAuth
97
98
  - cookies?: 需要额外添加到请求的 cookies, 默认情况下携带了 MemoryCookieStore 中保存的之前 http 响应中的 cookies
98
99
  - raw?: `false` 传入后返回整个 response (RawResponse),body 为 Readable
package/net.js CHANGED
@@ -40,7 +40,8 @@ let proxy_agents = {};
40
40
  async function request_retry(url, options, timeout, retries = 0, count = 0) {
41
41
  const { request: undici_request } = await import('undici');
42
42
  try {
43
- options.signal = AbortSignal.timeout(timeout);
43
+ if (timeout > 0)
44
+ options.signal = AbortSignal.timeout(timeout);
44
45
  return await undici_request(url, options);
45
46
  }
46
47
  catch (error) {
@@ -80,7 +81,7 @@ export async function request(url, options = {}) {
80
81
  let headers = {
81
82
  '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',
82
83
  'accept-encoding': 'gzip, deflate, br',
83
- 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36',
84
+ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
84
85
  'sec-ch-ua-platform': '"Windows"',
85
86
  'sec-ch-ua-platform-version': '"15.0.0"',
86
87
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xshell",
3
- "version": "1.0.95",
3
+ "version": "1.0.96",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "bin": {
@@ -53,14 +53,14 @@
53
53
  ]
54
54
  },
55
55
  "dependencies": {
56
- "@babel/core": "^7.24.4",
57
- "@babel/parser": "^7.24.4",
58
- "@babel/traverse": "^7.24.1",
56
+ "@babel/core": "^7.24.5",
57
+ "@babel/parser": "^7.24.5",
58
+ "@babel/traverse": "^7.24.5",
59
59
  "@koa/cors": "^5.0.0",
60
60
  "@types/ws": "^8.5.10",
61
- "@typescript-eslint/eslint-plugin": "^7.7.1",
62
- "@typescript-eslint/parser": "^7.7.1",
63
- "@typescript-eslint/utils": "^7.7.1",
61
+ "@typescript-eslint/eslint-plugin": "^7.8.0",
62
+ "@typescript-eslint/parser": "^7.8.0",
63
+ "@typescript-eslint/utils": "^7.8.0",
64
64
  "ali-oss": "^6.20.0",
65
65
  "archiver": "^7.0.1",
66
66
  "byte-size": "^8.1.1",
@@ -77,7 +77,7 @@
77
77
  "gulp-sort": "^2.0.0",
78
78
  "hash-string": "^1.0.0",
79
79
  "https-proxy-agent": "^7.0.4",
80
- "i18next": "^23.11.2",
80
+ "i18next": "^23.11.3",
81
81
  "i18next-scanner": "^4.4.0",
82
82
  "js-cookie": "^3.0.5",
83
83
  "koa": "^2.15.3",
@@ -86,27 +86,27 @@
86
86
  "map-stream": "0.0.7",
87
87
  "mime-types": "^2.1.35",
88
88
  "ora": "^8.0.1",
89
- "react": "^18.3.0",
89
+ "react": "^18.3.1",
90
90
  "react-i18next": "^14.1.1",
91
91
  "react-object-model": "^1.2.4",
92
92
  "resolve-path": "^1.4.0",
93
93
  "strip-ansi": "^7.1.0",
94
94
  "through2": "^4.0.2",
95
- "tough-cookie": "^4.1.3",
95
+ "tough-cookie": "^4.1.4",
96
96
  "tslib": "^2.6.2",
97
97
  "typescript": "^5.4.5",
98
98
  "ua-parser-js": "2.0.0-alpha.2",
99
- "undici": "^6.14.1",
99
+ "undici": "^6.15.0",
100
100
  "vinyl": "^3.0.0",
101
101
  "vinyl-fs": "^4.0.0",
102
- "ws": "^8.16.0",
102
+ "ws": "^8.17.0",
103
103
  "xterm": "^5.3.0",
104
104
  "xterm-addon-fit": "^0.8.0",
105
105
  "xterm-addon-web-links": "^0.9.0",
106
106
  "xterm-addon-webgl": "^0.16.0"
107
107
  },
108
108
  "devDependencies": {
109
- "@babel/types": "^7.24.0",
109
+ "@babel/types": "^7.24.5",
110
110
  "@types/ali-oss": "^6.16.11",
111
111
  "@types/archiver": "^6.0.2",
112
112
  "@types/babel__traverse": "^7.20.5",
@@ -121,7 +121,7 @@
121
121
  "@types/lodash": "^4.17.0",
122
122
  "@types/mime-types": "^2.1.4",
123
123
  "@types/node": "^20.12.7",
124
- "@types/react": "^18.3.0",
124
+ "@types/react": "^18.3.1",
125
125
  "@types/through2": "^2.0.41",
126
126
  "@types/tough-cookie": "^4.0.5",
127
127
  "@types/ua-parser-js": "^0.7.39",
@@ -115,6 +115,8 @@ declare global {
115
115
  /** 12.4 KB (1 KB = 1024 B) */
116
116
  to_fsize_str(this: number, units?: 'iec' | 'metric'): string;
117
117
  to_bin_str(this: number): string;
118
+ /** 转换为 0x???? 这样的十六进制形式
119
+ - length?: 位数自动对齐到 4 的倍数 */
118
120
  to_hex_str(this: number, length?: number): string;
119
121
  to_oct_str(this: number): string;
120
122
  }
@@ -394,11 +394,11 @@ Object.defineProperties(Number.prototype, to_method_property_descriptors({
394
394
  return `0b${this.toString(2)}`;
395
395
  },
396
396
  to_hex_str(length) {
397
- const s = this.toString(16);
397
+ const s = Math.abs(this).toString(16);
398
398
  // 长度自动对齐到 4 的倍数
399
- if (!length)
399
+ if (length === undefined)
400
400
  length = Math.ceil(s.length / 4) * 4;
401
- return `0x${'0'.repeat(length - s.length)}${s}`;
401
+ return `${this < 0 ? '-' : ''}0x${'0'.repeat(length - s.length)}${s}`;
402
402
  },
403
403
  to_oct_str() {
404
404
  return `0o${this.toString(8)}`;
package/prototype.d.ts CHANGED
@@ -139,6 +139,8 @@ declare global {
139
139
  /** 12.4 KB (1 KB = 1024 B) */
140
140
  to_fsize_str(this: number, units?: 'iec' | 'metric'): string;
141
141
  to_bin_str(this: number): string;
142
+ /** 转换为 0x???? 这样的十六进制形式
143
+ - length?: 位数自动对齐到 4 的倍数 */
142
144
  to_hex_str(this: number, length?: number): string;
143
145
  to_oct_str(this: number): string;
144
146
  }
package/prototype.js CHANGED
@@ -423,11 +423,11 @@ if (!globalThis.my_prototype_defined) {
423
423
  return `0b${this.toString(2)}`;
424
424
  },
425
425
  to_hex_str(length) {
426
- const s = this.toString(16);
426
+ const s = Math.abs(this).toString(16);
427
427
  // 长度自动对齐到 4 的倍数
428
- if (!length)
428
+ if (length === undefined)
429
429
  length = Math.ceil(s.length / 4) * 4;
430
- return `0x${'0'.repeat(length - s.length)}${s}`;
430
+ return `${this < 0 ? '-' : ''}0x${'0'.repeat(length - s.length)}${s}`;
431
431
  },
432
432
  to_oct_str() {
433
433
  return `0o${this.toString(8)}`;
package/server.d.ts CHANGED
@@ -93,9 +93,16 @@ export declare class Server {
93
93
  logger(ctx: Context): void;
94
94
  process_ua(ctx: Context): string;
95
95
  format_ua(headers: IncomingHttpHeaders | IncomingHttp2Headers): string;
96
- proxy(ctx: Context,
97
- /** 只含 host, path, 不含 queries 的 url */
98
- path_url: string | URL, headers_?: Record<string, string>, redirect?: RequestOptions['redirect']): Promise<true>;
96
+ /** 转发请求到其他 http 服务,实现网关的功能
97
+ - ctx
98
+ - path_url: 只含 host, path, 不含 queries 的 url, http://localhost:8080/api/get-user
99
+ 实际请求时会自动带上 ctx 中的 queries
100
+ - options?: ServerRequestOptions
101
+ - headers?: 修改 (添加、覆盖、null 值时删除) 请求的 http headers, Record<string, string | null>
102
+ - queries?: 修改 (添加、覆盖、null 值时删除) 请求的 http queries, Record<string, string | null>
103
+ - redirect?: `manual` 重定向处理策略,默认按原样返回给客户端
104
+ - timeout?: `1000 * 5` 请求超时时间,可以传入 0 禁用超时 */
105
+ request(ctx: Context, path_url: string | URL, { headers: headers_, redirect, queries, timeout }?: ServerRequestOptions): Promise<true>;
99
106
  static filter_response_headers(headers: RawResponse['headers']): Record<string, string>;
100
107
  /** 提供静态文件
101
108
  @example
@@ -127,3 +134,9 @@ export declare class Server {
127
134
  - reverse?: `false` 在 range 内从后往前尝试 */
128
135
  static get_available_port(range: string, reverse?: boolean): Promise<number>;
129
136
  }
137
+ export interface ServerRequestOptions {
138
+ headers?: Record<string, string | null>;
139
+ queries?: Record<string, string>;
140
+ redirect?: RequestOptions['redirect'];
141
+ timeout?: RequestOptions['timeout'];
142
+ }
package/server.js CHANGED
@@ -8,7 +8,7 @@ import util from 'util';
8
8
  // --- my libs
9
9
  import { t } from './i18n/instance.js';
10
10
  import { request as _request, Remote } from './net.js';
11
- import { inspect, output_width, assert, range_to_numbers, encode, filter_keys } from './utils.js';
11
+ import { inspect, output_width, assert, range_to_numbers, encode, filter_keys, filter_values } from './utils.js';
12
12
  import { flist, fread, fstat } from './file.js';
13
13
  // ------------ my server
14
14
  export class Server {
@@ -438,23 +438,36 @@ export class Server {
438
438
  }
439
439
  return s;
440
440
  }
441
- async proxy(ctx,
442
- /** 只含 host, path, 不含 queries 的 url */
443
- path_url, headers_ = {}, redirect = 'manual') {
441
+ /** 转发请求到其他 http 服务,实现网关的功能
442
+ - ctx
443
+ - path_url: 只含 host, path, 不含 queries url, 如 http://localhost:8080/api/get-user
444
+ 实际请求时会自动带上 ctx 中的 queries
445
+ - options?: ServerRequestOptions
446
+ - headers?: 修改 (添加、覆盖、null 值时删除) 请求的 http headers, Record<string, string | null>
447
+ - queries?: 修改 (添加、覆盖、null 值时删除) 请求的 http queries, Record<string, string | null>
448
+ - redirect?: `manual` 重定向处理策略,默认按原样返回给客户端
449
+ - timeout?: `1000 * 5` 请求超时时间,可以传入 0 禁用超时 */
450
+ async request(ctx, path_url, { headers: headers_, redirect, queries, timeout } = {}) {
444
451
  const { request: { method, headers, query, body, ip } } = ctx;
445
452
  let { response } = ctx;
453
+ const x_forwarded_for = headers['x-forwarded-for'] ? `${headers['x-forwarded-for']}, ${ip}` : ip;
446
454
  try {
447
455
  const response_ = await _request(path_url, {
448
456
  method: method,
449
- queries: query,
457
+ queries: queries
458
+ ? filter_values({ ...query, ...queries })
459
+ : query,
450
460
  body,
451
- headers: {
452
- ...headers,
453
- 'x-forwarded-for': headers['x-forwarded-for'] ? `${headers['x-forwarded-for']}, ${ip}` : ip,
454
- ...headers_
455
- },
461
+ headers: (headers_
462
+ ? filter_values({
463
+ ...headers,
464
+ 'x-forwarded-for': x_forwarded_for,
465
+ ...headers_
466
+ })
467
+ : { ...headers, 'x-forwarded-for': x_forwarded_for }),
456
468
  raw: true,
457
469
  redirect,
470
+ timeout
458
471
  });
459
472
  response.status = response_.status;
460
473
  response.set(Server.filter_response_headers(response_.headers));
@@ -1,4 +1,6 @@
1
1
  export declare const noop: () => void;
2
+ /** value 不为 null 或 undefined */
3
+ export declare const not_empty: (value: any) => boolean;
2
4
  export declare function assert(assertion: any, message?: string): never | void;
3
5
  export declare function log<T>(obj: T): T;
4
6
  /** 生成 0, 1, ..., n - 1 (不包括 n) 的数组,支持传入 generator 函数,通过 index 生成各个元素
@@ -56,7 +58,7 @@ export declare function encode(str: string): Uint8Array;
56
58
  在流式处理 (buffer 可能不完整) 时,应使用独立的 TextDecoder 实例调用 decode(buffer, { stream: true }) */
57
59
  export declare function decode(buffer: Uint8Array): string;
58
60
  /** 字符串字典序比较 */
59
- export declare function strcmp(l: string, r: string): 0 | 1 | -1;
61
+ export declare function strcmp(l: string, r: string): 1 | 0 | -1;
60
62
  /** 比较 1.10.02 这种版本号 */
61
63
  export declare function vercmp(l: string, r: string): number;
62
64
  export declare function get<TReturn = any>(obj: any, keypath: string): TReturn;
package/utils.browser.js CHANGED
@@ -1,5 +1,7 @@
1
1
  import { t } from './i18n/instance.js';
2
2
  export const noop = () => { };
3
+ /** value 不为 null 或 undefined */
4
+ export const not_empty = (value) => value !== null && value !== undefined;
3
5
  export function assert(assertion, message) {
4
6
  if (!assertion) {
5
7
  debugger;
package/utils.d.ts CHANGED
@@ -6,6 +6,8 @@ import util from 'util';
6
6
  import type Vinyl from 'vinyl';
7
7
  import './prototype.js';
8
8
  export declare const noop: () => void;
9
+ /** value 不为 null 或 undefined */
10
+ export declare const not_empty: (value: any) => boolean;
9
11
  /** `230` term 字符宽度 (实际上有 240) */
10
12
  export declare const output_width = 230;
11
13
  export declare function set_inspect_options(colors?: boolean): void;
@@ -31,10 +33,12 @@ export declare function map_values<TValue, TNewValue>(obj: {
31
33
  };
32
34
  /** 过滤对象中的 keys, 返回新对象 */
33
35
  export declare function filter_keys<TObj>(obj: TObj, filter: (key: string) => any): TObj;
36
+ /** 过滤对象中的 keys, 返回新对象 */
37
+ export declare function filter_values<TObj extends Record<string, any>>(obj: TObj, filter?: (value: TObj[string]) => any): TObj;
34
38
  /** 忽略对象中的 keys, 返回新对象 */
35
39
  export declare function omit<TObj>(obj: TObj, omit_keys: string[]): TObj;
36
40
  /** 字符串字典序比较 */
37
- export declare function strcmp(l: string, r: string): 0 | 1 | -1;
41
+ export declare function strcmp(l: string, r: string): 1 | 0 | -1;
38
42
  /** 比较 1.10.02 这种版本号 */
39
43
  export declare function vercmp(l: string, r: string): number;
40
44
  export declare function get<TReturn = any>(obj: any, keypath: string): TReturn;
package/utils.js CHANGED
@@ -3,6 +3,8 @@ import util from 'util';
3
3
  import { t } from './i18n/instance.js';
4
4
  import './prototype.js';
5
5
  export const noop = () => { };
6
+ /** value 不为 null 或 undefined */
7
+ export const not_empty = (value) => value !== null && value !== undefined;
6
8
  /** `230` term 字符宽度 (实际上有 240) */
7
9
  export const output_width = 230;
8
10
  export function set_inspect_options(colors = true) {
@@ -97,6 +99,11 @@ export function filter_keys(obj, filter) {
97
99
  return Object.fromEntries(Object.entries(obj)
98
100
  .filter(([key]) => filter(key)));
99
101
  }
102
+ /** 过滤对象中的 keys, 返回新对象 */
103
+ export function filter_values(obj, filter = not_empty) {
104
+ return Object.fromEntries(Object.entries(obj)
105
+ .filter(([, value]) => filter(value)));
106
+ }
100
107
  /** 忽略对象中的 keys, 返回新对象 */
101
108
  export function omit(obj, omit_keys) {
102
109
  const omit_keys_ = new Set(omit_keys);