xshell 1.3.6 → 1.3.8

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/builder.d.ts CHANGED
@@ -53,6 +53,8 @@ interface AssetOption {
53
53
  src: string;
54
54
  /** 相对 fpd_out 的路径,或者绝对路径,默认等于 src 的值 */
55
55
  out?: string;
56
+ /** 直接设置 html 的路径,强制覆盖 */
57
+ value?: string;
56
58
  }
57
59
  type Assets = {
58
60
  productions?: (string | AssetOption)[];
@@ -127,7 +129,7 @@ export declare class Bundler {
127
129
  - target: 目标环境 nodejs | web
128
130
  - fpd_root: 项目根目录
129
131
  - fpd_out: 输出文件目录
130
- - fpd_cache: webpack 缓存目录
132
+ - fpdt_cache?: webpack 缓存目录,可以设置为 undefined 使用默认路径 node_modules/.cache/webpack/
131
133
  - entry: 入口文件
132
134
  - options?: 打包配置, 按常用顺序排列
133
135
  - production?: `true` webpack mode 设置为 'production'
package/builder.js CHANGED
@@ -104,7 +104,7 @@ const dependencies = {
104
104
  function get_asset_out(asset) {
105
105
  return typeof asset === 'string'
106
106
  ? asset
107
- : asset.out || asset.src;
107
+ : asset.value || asset.out || asset.src;
108
108
  }
109
109
  function get_vendor_asset_out(asset) {
110
110
  return typeof asset === 'string'
@@ -152,7 +152,7 @@ export class Bundler {
152
152
  - target: 目标环境 nodejs | web
153
153
  - fpd_root: 项目根目录
154
154
  - fpd_out: 输出文件目录
155
- - fpd_cache: webpack 缓存目录
155
+ - fpdt_cache?: webpack 缓存目录,可以设置为 undefined 使用默认路径 node_modules/.cache/webpack/
156
156
  - entry: 入口文件
157
157
  - options?: 打包配置, 按常用顺序排列
158
158
  - production?: `true` webpack mode 设置为 'production'
package/development.js CHANGED
@@ -26,10 +26,10 @@ export function process_stdin(on_key, on_exit) {
26
26
  }
27
27
  /** 自动配置项目 vscode 设置 */
28
28
  export async function setup_vscode_settings(fpd_root) {
29
- if (!ramdisk) {
30
- const fp_settings = `${fpd_root}.vscode/settings.json`;
31
- if (!fexists(fp_settings, noprint))
32
- await fcopy(`${fp_settings.strip_end('json')}template.json`, fp_settings);
33
- }
29
+ if (ramdisk)
30
+ return;
31
+ const fp_settings = `${fpd_root}.vscode/settings.json`;
32
+ if (!fexists(fp_settings, noprint))
33
+ await fcopy(`${fp_settings.strip_end('json')}template.json`, fp_settings);
34
34
  }
35
35
  //# sourceMappingURL=development.js.map
package/file.js CHANGED
@@ -747,8 +747,10 @@ export async function ftail(fp, handler, { print = true } = {}) {
747
747
  }
748
748
  /** 打开一个文件并搜索替换某个 pattern */
749
749
  export async function freplace(fp, pattern, replacement, { print = true } = {}) {
750
- await fwrite(fp, (await fread(fp, { print }))
751
- .replaceAll(pattern, replacement), { print });
750
+ await fwrite(fp, (await fread(fp, noprint))
751
+ .replaceAll(pattern, replacement), noprint);
752
+ if (print)
753
+ console.log('替换了:', fp);
752
754
  }
753
755
  /** 同步文件或文件夹 fp_src 到 fp_dst ,返回 fp_dst
754
756
  - fp_src: 源文件或文件夹
package/fzip.js CHANGED
@@ -60,9 +60,7 @@ async function _zip(data, fp_zip, { dirname, print = { files: true, info: true }
60
60
  });
61
61
  ostream.once('error', reject);
62
62
  archive.once('error', reject);
63
- archive.on('warning', error => {
64
- console.log(error);
65
- });
63
+ archive.on('warning', console.warn);
66
64
  archive.pipe(ostream);
67
65
  for (const fp in entries) {
68
66
  const fdata = entries[fp];
package/net.common.d.ts CHANGED
@@ -11,23 +11,6 @@ export interface BearerAuth {
11
11
  type: 'bearer';
12
12
  token: string;
13
13
  }
14
- /** 自动保持 remote 连接,只对 initiator 且传入 url 有效,
15
- - 在未连接,或 websocket on_error 检测到连接断开后以 reconnect_interval 间隔尝试 remote.call(func) 重连
16
- - 在连接状态下以 heartbeat_interval 间隔发送心跳包确保连接状态
17
-
18
- 配置选项:
19
- - func?: 连接后调用的函数,通常为某个 register 函数,将自身注册到 server
20
- - args?: 连接后调用函数时传递的参数,与 func 配合使用
21
- - reconnect_interval?: `1000 * 5` 首次重连失败后的后续尝试间隔 (单位: ms)
22
- - heartbeat_interval?: `1000 * 60` 发送心跳包确保连接的间隔 (单位: ms)
23
- - error_delay?: `2000` 遇到错误时首次尝试重连的延时 (单位: ms) */
24
- export interface RemoteKeeperOptions {
25
- func?: string;
26
- args?: any[];
27
- reconnect_interval?: number;
28
- heartbeat_interval?: number;
29
- error_delay?: number;
30
- }
31
14
  export declare const WebSocketConnecting = 0;
32
15
  export declare const WebSocketOpen = 1;
33
16
  export declare const WebSocketClosing = 2;
@@ -49,6 +32,21 @@ export declare class WebSocketConnectionError extends Error {
49
32
  static get_reason_string(code: number | string, reason?: string): string | number;
50
33
  constructor(url: string, protocols: string[] | undefined, event?: CloseEvent | ErrorEvent, message?: string);
51
34
  }
35
+ export interface ConnectWebSocketPrint {
36
+ connect: boolean;
37
+ error: boolean;
38
+ close: boolean;
39
+ }
40
+ export interface ConnectWebsocketOptions {
41
+ print?: boolean | ConnectWebSocketPrint;
42
+ protocols?: string[];
43
+ max_payload?: number;
44
+ proxy?: string;
45
+ on_message(data: ArrayBuffer | string, websocket: WebSocket): any;
46
+ on_error?(error: WebSocketConnectionError, websocket: WebSocket): any;
47
+ on_close?(event: CloseEvent, websocket: WebSocket): any;
48
+ connect?: (typeof import('tls'))['connect'] | (typeof import('net'))['connect'];
49
+ }
52
50
  /** 连接 websocket url, 设置各种事件监听器。在 open 事件后 resolve, 返回 websocket
53
51
  遇到 error, close 事件时会创建 WebSocketConnectionError:
54
52
  - reject 掉返回的 promise (若此时未 settle)
@@ -57,7 +55,9 @@ export declare class WebSocketConnectionError extends Error {
57
55
  https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/bufferedAmount
58
56
  - url
59
57
  - options:
60
- - print?: 是否打印连接、关闭信息
58
+ - print?: boolean 或者 ConnectWebSocketPrint,可以控制是否打印连接、正常断开、关闭信息
59
+ - connect: `true` 连接建立
60
+ - error: `true` 出错
61
61
  - protocols?
62
62
  - max_payload?: `8 gb` (仅 nodejs 环境有效)
63
63
  - proxy?: string (仅 nodejs 环境有效)
@@ -66,17 +66,10 @@ export declare class WebSocketConnectionError extends Error {
66
66
  - on_error?: 在 websocket 出错和非正常关闭 (close, error 事件) 时都调用,可以根据 error.type 来区分,error 的类型是 WebSocketConnectionError,
67
67
  type 为 'close' 时有 code 和 reason 属性
68
68
  - on_close?: 和 websocket 的 'close' 事件不相同,只在正常关闭 (close code 为 1000) 时才调用,否则都会调用 on_error
69
- https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes */
69
+ https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes
70
+ - connect?: nodejs 环境下需要指定 ip, port 手动连接 tls server 时使用,有 agent 时不生效 */
70
71
  export declare function connect_websocket(url: string | URL, { print, protocols, max_payload, // 8 GB
71
- proxy, on_message, on_error, on_close, }: {
72
- print?: boolean;
73
- protocols?: string[];
74
- max_payload?: number;
75
- proxy?: string;
76
- on_message(data: ArrayBuffer | string, websocket: WebSocket): any;
77
- on_error?(error: WebSocketConnectionError, websocket: WebSocket): any;
78
- on_close?(event: CloseEvent, websocket: WebSocket): any;
79
- }): Promise<WebSocket>;
72
+ proxy, on_message, on_error, on_close, connect }: ConnectWebsocketOptions): Promise<WebSocket>;
80
73
  /** 接收到消息后的处理函数
81
74
  返回值会自动被 await,然后可能被封装为 message 回传 */
82
75
  export type MessageHandler<TData = any> = (message: Message<TData>, remote: Remote) => void | any | Promise<void | any>;
@@ -102,6 +95,8 @@ export interface RemoteOptions {
102
95
  on_error?(error: WebSocketConnectionError | Error, remote: Remote): void;
103
96
  /** 使用者自定义的,在重连之前调用的函数,比如可以修改 url,仅连接发起方有效 */
104
97
  on_reconnect?(this: Remote): Promise<void>;
98
+ /** 使用者自定义的,在连接建立,包括首次连接和重连 之后调用的函数,比如可以重新调用一些函数,仅连接发起方有效 */
99
+ on_connected?(this: Remote): void;
105
100
  }
106
101
  /** 通过创建 remote 对象对 websocket rpc 进行抽象
107
102
  使用 remote.call() 进行一元 rpc
@@ -148,10 +143,11 @@ export declare class Remote {
148
143
  error: WebSocketConnectionError | Error;
149
144
  /** 作为 websocket 连接发起方,传入 url
150
145
  作为 websocket 连接接收方,传入 websocket + name */
151
- constructor({ name, url, websocket, funcs, print, verbose, probe, args, on_error, on_reconnect }?: RemoteOptions);
146
+ constructor({ name, url, websocket, funcs, print, verbose, probe, args, on_error, on_reconnect, on_connected }?: RemoteOptions);
152
147
  /** 统一处理首次连接和连接后的 websocket 错误 */
153
148
  _on_error: (error: WebSocketConnectionError | Error) => void;
154
149
  on_reconnect?: (this: Remote) => Promise<void>;
150
+ on_connected?: (this: Remote) => void;
155
151
  reconnect: () => Promise<void>;
156
152
  _on_message: (data: ArrayBuffer) => void;
157
153
  /** 使用者自定义的在 websocket 连接出错时,或者 handlers 出错时的处理
package/net.common.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { platform } from "./platform.common.js";
2
2
  import { rethrow } from "./prototype.common.js"; // .bracket()
3
3
  import { message_symbol, pack, parse } from "./io.common.js";
4
- import { check, defer, delay, genid, Lock, set_error_message, timeout, TimeoutError } from "./utils.common.js";
4
+ import { check, defer, defer2, delay, genid, Lock, nowstr, set_error_message, timeout, TimeoutError } from "./utils.common.js";
5
5
  import { t } from "./i18n/instance.js";
6
6
  /** 对于 request() 函数来说无意义的 headers,会自动过滤掉 */
7
7
  export const drop_request_headers = new Set([
@@ -50,16 +50,7 @@ export class WebSocketConnectionError extends Error {
50
50
  if (event)
51
51
  if ((type = event.type) === 'error') {
52
52
  ({ error } = event);
53
- if (error) {
54
- ({ code, reason } = error);
55
- message = `${t('连接被关闭')}: ` + [
56
- error.message,
57
- WebSocketConnectionError.get_reason_string(code, reason),
58
- error.syscall ? `${error.syscall}(${error.errno})` : ''
59
- ].filter(Boolean).join(' ');
60
- }
61
- else
62
- message = t('连接被关闭');
53
+ message = error ? `${t('连接被关闭')}: ${error.message}` : t('连接被关闭');
63
54
  }
64
55
  else {
65
56
  ({ code, reason } = event);
@@ -67,7 +58,7 @@ export class WebSocketConnectionError extends Error {
67
58
  }
68
59
  else
69
60
  message = t('连接被关闭');
70
- super(new Date().to_time_str() + ' ' +
61
+ super(nowstr() + ' ' +
71
62
  (url || '传入') +
72
63
  (protocols ? ' ' + protocols.join(', ').bracket() : '') +
73
64
  ' ' + message);
@@ -97,7 +88,9 @@ let websocket_proxy_agents = {};
97
88
  https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/bufferedAmount
98
89
  - url
99
90
  - options:
100
- - print?: 是否打印连接、关闭信息
91
+ - print?: boolean 或者 ConnectWebSocketPrint,可以控制是否打印连接、正常断开、关闭信息
92
+ - connect: `true` 连接建立
93
+ - error: `true` 出错
101
94
  - protocols?
102
95
  - max_payload?: `8 gb` (仅 nodejs 环境有效)
103
96
  - proxy?: string (仅 nodejs 环境有效)
@@ -106,10 +99,21 @@ let websocket_proxy_agents = {};
106
99
  - on_error?: 在 websocket 出错和非正常关闭 (close, error 事件) 时都调用,可以根据 error.type 来区分,error 的类型是 WebSocketConnectionError,
107
100
  type 为 'close' 时有 code 和 reason 属性
108
101
  - on_close?: 和 websocket 的 'close' 事件不相同,只在正常关闭 (close code 为 1000) 时才调用,否则都会调用 on_error
109
- https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes */
110
- export async function connect_websocket(url, { print = true, protocols, max_payload = 2 ** 33, // 8 GB
111
- proxy, on_message, on_error, on_close, }) {
102
+ https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes
103
+ - connect?: nodejs 环境下需要指定 ip, port 手动连接 tls server 时使用,有 agent 时不生效 */
104
+ export async function connect_websocket(url, { print = {
105
+ connect: true,
106
+ error: true,
107
+ close: true
108
+ }, protocols, max_payload = 2 ** 33, // 8 GB
109
+ proxy, on_message, on_error, on_close, connect }) {
112
110
  const { nodejs } = platform;
111
+ if (typeof print === 'boolean')
112
+ print = {
113
+ connect: print,
114
+ error: print,
115
+ close: print
116
+ };
113
117
  let websocket = new (await platform.get_websocket())(url, protocols,
114
118
  // @ts-ignore
115
119
  nodejs ?
@@ -119,78 +123,60 @@ proxy, on_message, on_error, on_close, }) {
119
123
  allowSynchronousEvents: true,
120
124
  ...proxy ? {
121
125
  agent: websocket_proxy_agents[proxy] ??= new (await platform.get_https_proxy_agent())(proxy)
122
- } : {}
126
+ } : {},
127
+ ...connect ? { createConnection: connect } : {}
123
128
  }
124
129
  :
125
130
  undefined);
126
131
  // https://stackoverflow.com/questions/11821096/what-is-the-difference-between-an-arraybuffer-and-a-blob/39951543
127
132
  websocket.binaryType = 'arraybuffer';
128
- return new Promise((resolve, reject) => {
129
- let settled = false;
130
- // websocket error, close 事件只选一个最详细的构造 WebSocketConnectionError 并调用 on_error
131
- let errored;
132
- websocket.addEventListener('open', event => {
133
- if (print)
134
- console.log(websocket.url +
135
- (websocket.protocol ? ' ' + websocket.protocol.bracket() : '') +
136
- t(' 已连接'));
137
- settled = true;
138
- resolve(websocket);
139
- }, { once: true });
140
- // error 事件会先于 close 事件
141
- // node.js 环境下 error 事件的错误信息比较多,浏览器环境下 close 的错误信息比较多
142
- // 在浏览器环境下延后处理 error 事件,放到微任务队列之后的 timers 队列中
143
- // https://blog.insiderattack.net/promises-next-ticks-and-immediates-nodejs-event-loop-part-3-9226cbe7a6aa
144
- function on_close_or_error(event) {
145
- websocket.removeEventListener('message', _on_message);
146
- const { type } = event;
147
- // 正常关闭
148
- if (type === 'close' && event.code === 1000) {
149
- if (on_close)
150
- on_close(event, websocket);
151
- else if (print)
152
- console.log(`${websocket.url} 已正常关闭`);
153
- return;
154
- }
155
- // 观察一段时间,在 nodejs 中应该没有先 close 再 error 的情况
156
- if (errored === 'close' && platform.nodejs) {
157
- console.warn('在 nodejs 中应该没有先 close 再 error 的情况', event.error);
158
- errored = null;
159
- }
160
- // 已经调用过 on_error 了
161
- if (errored)
162
- return;
163
- errored = type;
164
- const error = new WebSocketConnectionError(websocket.url, protocols, event);
165
- if (!settled) {
166
- settled = true;
167
- reject(error);
168
- return;
169
- }
170
- if (on_error)
171
- on_error(error, websocket);
172
- else if (print)
173
- console.log(error);
133
+ let pwebsocket = defer2();
134
+ websocket.addEventListener('open', event => {
135
+ if (print.connect)
136
+ console.log(websocket.url +
137
+ (websocket.protocol ? ' ' + websocket.protocol.bracket() : '') +
138
+ t(' 已连接'));
139
+ pwebsocket.resolve(websocket);
140
+ }, { once: true });
141
+ // websocket error, close 事件只选一个最详细的构造 WebSocketConnectionError 并调用 on_error
142
+ // error 事件会先于 close 事件
143
+ // node.js 环境下 error 事件的错误信息比较多,而浏览器环境下 close 的错误信息比较多
144
+ // 在浏览器环境下延后处理 error 事件,放到微任务队列之后的 timers 队列中
145
+ // https://blog.insiderattack.net/promises-next-ticks-and-immediates-nodejs-event-loop-part-3-9226cbe7a6aa
146
+ let errored;
147
+ function on_close_or_error(event) {
148
+ const { type } = event;
149
+ // 正常关闭
150
+ if (type === 'close' && event.code === 1000) {
151
+ if (on_close)
152
+ on_close(event, websocket);
153
+ else if (print.close)
154
+ console.log(`${websocket.url} ${t('已正常关闭')}`);
155
+ return;
174
156
  }
175
- // 检查实际情况下 error 事件会先于 close 事件,观察一段时间后可删去
176
- let closed = false;
177
- websocket.addEventListener('error', (event) => {
178
- if (closed)
179
- console.warn('close 事件先于 error 事件发生,奇怪!');
180
- if (nodejs)
181
- on_close_or_error(event);
182
- else
183
- setTimeout(() => { on_close_or_error(event); });
184
- }, { once: true });
185
- websocket.addEventListener('close', event => {
186
- closed = true;
157
+ // 已经调用过 on_error
158
+ if (errored)
159
+ return;
160
+ errored = type;
161
+ const error = new WebSocketConnectionError(websocket.url, protocols, event);
162
+ if (!pwebsocket.settled)
163
+ pwebsocket.reject(error);
164
+ else if (on_error)
165
+ on_error(error, websocket);
166
+ else if (print.error)
167
+ console.error(error.message);
168
+ }
169
+ websocket.addEventListener('error', (event) => {
170
+ if (nodejs)
187
171
  on_close_or_error(event);
188
- }, { once: true });
189
- function _on_message(event) {
190
- on_message(event.data, websocket);
191
- }
192
- websocket.addEventListener('message', _on_message);
172
+ else
173
+ setTimeout(() => { on_close_or_error(event); });
174
+ }, { once: true });
175
+ websocket.addEventListener('close', on_close_or_error, { once: true });
176
+ websocket.addEventListener('message', event => {
177
+ on_message(event.data, websocket);
193
178
  });
179
+ return pwebsocket;
194
180
  }
195
181
  /** 通过创建 remote 对象对 websocket rpc 进行抽象
196
182
  使用 remote.call() 进行一元 rpc
@@ -238,7 +224,7 @@ export class Remote {
238
224
  error;
239
225
  /** 作为 websocket 连接发起方,传入 url
240
226
  作为 websocket 连接接收方,传入 websocket + name */
241
- constructor({ name, url, websocket, funcs, print, verbose, probe, args, on_error, on_reconnect } = {}) {
227
+ constructor({ name, url, websocket, funcs, print, verbose, probe, args, on_error, on_reconnect, on_connected } = {}) {
242
228
  if (name)
243
229
  this.name = name;
244
230
  if (url) {
@@ -246,17 +232,19 @@ export class Remote {
246
232
  this.url = url;
247
233
  if (on_reconnect)
248
234
  this.on_reconnect = on_reconnect;
235
+ if (on_connected)
236
+ this.on_connected = on_connected;
249
237
  }
250
238
  else { // 连接接收方,一定是 nodejs 环境
251
239
  check(websocket, '构建 Remote 时需传入 url 或者 websocket');
252
240
  this.lwebsocket.resource = websocket;
253
241
  websocket.binaryType = 'arraybuffer';
254
242
  // 参考 connect_websocket 实现
255
- let errored = false;
243
+ let errored;
256
244
  const on_close_or_error = (event) => {
257
- websocket.removeEventListener('message', _on_message);
245
+ const { type } = event;
258
246
  // 正常关闭
259
- if (event.type === 'close' && event.code === 1000) {
247
+ if (type === 'close' && event.code === 1000) {
260
248
  if (print)
261
249
  console.log(`${this.name || websocket.url || '传入连接'} 已正常关闭`);
262
250
  return;
@@ -264,24 +252,14 @@ export class Remote {
264
252
  // 已经调用过 on_error 了
265
253
  if (errored)
266
254
  return;
267
- errored = true;
255
+ errored = type;
268
256
  this._on_error(new WebSocketConnectionError(this.name || websocket.url, websocket.protocol ? [websocket.protocol] : undefined, event));
269
257
  };
270
- // 检查实际情况下 error 事件会先于 close 事件,观察一段时间后可删去
271
- let closed = false;
272
- websocket.addEventListener('error', (event) => {
273
- if (closed)
274
- console.warn('close 事件先于 error 事件发生,奇怪!');
275
- on_close_or_error(event);
276
- }, { once: true });
277
- websocket.addEventListener('close', event => {
278
- closed = true;
279
- on_close_or_error(event);
280
- }, { once: true });
281
- const _on_message = (event) => {
258
+ websocket.addEventListener('error', on_close_or_error, { once: true });
259
+ websocket.addEventListener('close', on_close_or_error, { once: true });
260
+ websocket.addEventListener('message', event => {
282
261
  this._on_message(event.data);
283
- };
284
- websocket.addEventListener('message', _on_message);
262
+ });
285
263
  }
286
264
  if (funcs) {
287
265
  check(!funcs.echo);
@@ -316,6 +294,7 @@ export class Remote {
316
294
  this.on_error(error, this);
317
295
  };
318
296
  on_reconnect;
297
+ on_connected;
319
298
  reconnect = async () => {
320
299
  this.reconnecting = null;
321
300
  if (this.on_reconnect)
@@ -389,6 +368,7 @@ export class Remote {
389
368
  this.error = null;
390
369
  if (this.args)
391
370
  await this.call('register', this.args);
371
+ this.on_connected?.();
392
372
  };
393
373
  /** 尝试建立连接,通常用于开始保活
394
374
  重连错误会在 this.connect 里面调用 this._on_error 处理 */
package/net.js CHANGED
@@ -3,7 +3,7 @@ import net from 'node:net';
3
3
  import { buffer as stream_to_buffer, text as stream_to_text } from 'node:stream/consumers';
4
4
  import { pipeline, isReadable } from 'node:stream';
5
5
  import { noop } from "./prototype.js";
6
- import { inspect, assert, delay, map_values, unique, timeout, check, colored, encode, TimeoutError, set_error_message, defer2 } from "./utils.js";
6
+ import { inspect, assert, delay, map_values, unique, timeout, check, colored, encode, TimeoutError, set_error_message, defer2, nowstr } from "./utils.js";
7
7
  import { drop_request_headers } from "./net.common.js";
8
8
  export * from "./net.common.js";
9
9
  export var MyProxy;
@@ -308,7 +308,7 @@ export function connect(hostname, port, { local_port, timeout: _timeout = 2000,
308
308
  let pconnected = defer2();
309
309
  let timeouted = false;
310
310
  function get_message(message) {
311
- return `tcp://${hostname}:${port} ${message}`;
311
+ return `${nowstr()} tcp://${hostname}:${port} ${message}`;
312
312
  }
313
313
  let socket = net.connect({
314
314
  host: hostname,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xshell",
3
- "version": "1.3.6",
3
+ "version": "1.3.8",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "bin": {
@@ -53,12 +53,12 @@
53
53
  "@babel/parser": "^7.28.5",
54
54
  "@babel/traverse": "^7.28.5",
55
55
  "@koa/cors": "^5.0.0",
56
- "@stylistic/eslint-plugin": "^5.5.0",
56
+ "@stylistic/eslint-plugin": "^5.6.1",
57
57
  "@svgr/webpack": "^8.1.0",
58
58
  "@types/sass-loader": "^8.0.10",
59
- "@typescript-eslint/eslint-plugin": "^8.46.3",
60
- "@typescript-eslint/parser": "^8.46.3",
61
- "@typescript-eslint/utils": "^8.46.3",
59
+ "@typescript-eslint/eslint-plugin": "^8.47.0",
60
+ "@typescript-eslint/parser": "^8.47.0",
61
+ "@typescript-eslint/utils": "^8.47.0",
62
62
  "archiver": "^7.0.1",
63
63
  "chalk": "^5.6.2",
64
64
  "commander": "^14.0.2",
@@ -68,17 +68,17 @@
68
68
  "eslint-plugin-import": "^2.32.0",
69
69
  "eslint-plugin-react": "^7.37.5",
70
70
  "https-proxy-agent": "^7.0.6",
71
- "i18next": "^25.6.1",
71
+ "i18next": "^25.6.3",
72
72
  "i18next-scanner": "^4.6.0",
73
73
  "koa": "^3.1.1",
74
74
  "koa-compress": "^5.1.1",
75
75
  "license-webpack-plugin": "^4.0.2",
76
76
  "mime-types": "^3.0.1",
77
- "p-map": "^7.0.3",
77
+ "p-map": "^7.0.4",
78
78
  "react": "^19.2.0",
79
- "react-i18next": "^16.2.4",
79
+ "react-i18next": "^16.3.4",
80
80
  "resolve-path": "^1.4.0",
81
- "sass": "^1.93.3",
81
+ "sass": "^1.94.1",
82
82
  "sass-loader": "^16.0.6",
83
83
  "source-map-loader": "^5.0.0",
84
84
  "strip-ansi": "^7.1.2",
@@ -88,8 +88,8 @@
88
88
  "tslib": "^2.8.1",
89
89
  "typescript": "^5.9.3",
90
90
  "undici": "^7.16.0",
91
- "webpack": "^5.102.1",
92
- "webpack-bundle-analyzer": "^4.10.2",
91
+ "webpack": "^5.103.0",
92
+ "webpack-bundle-analyzer": "^5.0.1",
93
93
  "ws": "^8.18.3"
94
94
  },
95
95
  "devDependencies": {
@@ -101,10 +101,10 @@
101
101
  "@types/koa": "^3.0.1",
102
102
  "@types/koa-compress": "^4.0.7",
103
103
  "@types/mime-types": "^3.0.1",
104
- "@types/node": "^24.10.0",
105
- "@types/react": "^19.2.2",
104
+ "@types/node": "^24.10.1",
105
+ "@types/react": "^19.2.6",
106
106
  "@types/tough-cookie": "^4.0.5",
107
- "@types/vscode": "^1.105.0",
107
+ "@types/vscode": "^1.106.1",
108
108
  "@types/webpack-bundle-analyzer": "^4.7.0",
109
109
  "@types/ws": "^8.18.1"
110
110
  }
package/utils.common.d.ts CHANGED
@@ -6,6 +6,8 @@ export declare function assert<T>(assertion: T, message?: string): T;
6
6
  export declare function check<T>(condition: T, message?: string): T;
7
7
  /** 生成随机 id (number) */
8
8
  export declare function genid(): number;
9
+ /** 生成随机 uint32 */
10
+ export declare function genu32(): number;
9
11
  /** 通过 console.log 打印对象并返回
10
12
  @example
11
13
  log('label', obj)
package/utils.common.js CHANGED
@@ -23,6 +23,10 @@ export function check(condition, message) {
23
23
  export function genid() {
24
24
  return Math.random() * 2 ** 53;
25
25
  }
26
+ /** 生成随机 uint32 */
27
+ export function genu32() {
28
+ return Math.random() * 2 ** 32 >>> 0;
29
+ }
26
30
  export function log(...args) {
27
31
  if (args.length === 2) {
28
32
  const [label, obj] = args;
@@ -215,7 +219,7 @@ export function timeout(milliseconds, action, on_timeout, print = true) {
215
219
  paction.then(result => {
216
220
  if (presult.settled) {
217
221
  if (print)
218
- console.log('已超时任务最终完成了');
222
+ console.log('已超时任务最终完成了:', result);
219
223
  }
220
224
  else if (!waiting_on_timeout) {
221
225
  presult.resolve(result);
package/utils.js CHANGED
@@ -31,14 +31,14 @@ export function typed_array_to_buffer(view) {
31
31
  - hour: 0 - 23 之间的整数,在这个点执行
32
32
  - action */
33
33
  export async function schedule_everyday(hour, action) {
34
- const now = new Date();
34
+ const now = Date.now();
35
35
  let target = new Date();
36
36
  target.setHours(hour, 0, 0, 0);
37
37
  // 如果目标时间已过,设定为明天的时间
38
- if (now.getTime() > target.getTime())
38
+ if (now > target.getTime())
39
39
  target.setDate(target.getDate() + 1);
40
40
  // 等时间到
41
- await delay(target.getTime() - now.getTime());
41
+ await delay(target.getTime() - now);
42
42
  for (;;) {
43
43
  try {
44
44
  await action();