xshell 1.3.8 → 1.3.9

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/net.common.d.ts CHANGED
@@ -1,5 +1,11 @@
1
+ import type { Socket } from 'node:net';
1
2
  import { type Message } from './io.common.ts';
2
3
  import { Lock, TimeoutError } from './utils.common.ts';
4
+ declare global {
5
+ interface WebSocket {
6
+ _socket?: Socket;
7
+ }
8
+ }
3
9
  /** 对于 request() 函数来说无意义的 headers,会自动过滤掉 */
4
10
  export declare const drop_request_headers: Set<string>;
5
11
  export interface BasicAuth {
@@ -42,6 +48,7 @@ export interface ConnectWebsocketOptions {
42
48
  protocols?: string[];
43
49
  max_payload?: number;
44
50
  proxy?: string;
51
+ keep_alive_duration?: number;
45
52
  on_message(data: ArrayBuffer | string, websocket: WebSocket): any;
46
53
  on_error?(error: WebSocketConnectionError, websocket: WebSocket): any;
47
54
  on_close?(event: CloseEvent, websocket: WebSocket): any;
@@ -61,6 +68,7 @@ export interface ConnectWebsocketOptions {
61
68
  - protocols?
62
69
  - max_payload?: `8 gb` (仅 nodejs 环境有效)
63
70
  - proxy?: string (仅 nodejs 环境有效)
71
+ - keep_alive_duration?: 毫秒数,设置后启用操作系统级的 keep alive (仅 nodejs 环境可以有效,浏览器端默认已启用)
64
72
  - on_message: 根据 websocket frame 的 opcode 不同 (text frame 或 binary frame),event 中的 data 对应为 ArrayBuffer 或者 string
65
73
  https://datatracker.ietf.org/doc/html/rfc6455#section-5.2
66
74
  - on_error?: 在 websocket 出错和非正常关闭 (close, error 事件) 时都调用,可以根据 error.type 来区分,error 的类型是 WebSocketConnectionError,
@@ -69,7 +77,7 @@ export interface ConnectWebsocketOptions {
69
77
  https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes
70
78
  - connect?: nodejs 环境下需要指定 ip, port 手动连接 tls server 时使用,有 agent 时不生效 */
71
79
  export declare function connect_websocket(url: string | URL, { print, protocols, max_payload, // 8 GB
72
- proxy, on_message, on_error, on_close, connect }: ConnectWebsocketOptions): Promise<WebSocket>;
80
+ proxy, keep_alive_duration, on_message, on_error, on_close, connect }: ConnectWebsocketOptions): Promise<WebSocket>;
73
81
  /** 接收到消息后的处理函数
74
82
  返回值会自动被 await,然后可能被封装为 message 回传 */
75
83
  export type MessageHandler<TData = any> = (message: Message<TData>, remote: Remote) => void | any | Promise<void | any>;
@@ -82,8 +90,12 @@ export interface RemoteOptions {
82
90
  websocket?: WebSocket;
83
91
  /** 能被对端调用的函数 */
84
92
  funcs?: Remote['funcs'];
85
- /** `false` 是否启用主动探测连接,在连接状态下以 30s 间隔发送心跳包确保连接状态 */
86
- probe?: boolean;
93
+ /** 设置后启用操作系统级的 keep alive (仅 nodejs 环境可设置)
94
+ - 浏览器端有默认 tcp keep alive 心跳机制,禁止设置这个参数
95
+ - nodejs 端
96
+ - 作为连接发起方: 在 websocket 连接建立时启用
97
+ - 作为连接接收方: 在根据传入 websocket 创建 Remote 时启用 */
98
+ alive?: boolean;
87
99
  /** websocket 连接建立成功时调用对端 register 函数的参数 (仅发起方有效) */
88
100
  args?: any[];
89
101
  /** `true` 是否打印连接信息、错误信息 */
@@ -95,7 +107,8 @@ export interface RemoteOptions {
95
107
  on_error?(error: WebSocketConnectionError | Error, remote: Remote): void;
96
108
  /** 使用者自定义的,在重连之前调用的函数,比如可以修改 url,仅连接发起方有效 */
97
109
  on_reconnect?(this: Remote): Promise<void>;
98
- /** 使用者自定义的,在连接建立,包括首次连接和重连 之后调用的函数,比如可以重新调用一些函数,仅连接发起方有效 */
110
+ /** 使用者自定义的,在连接建立,包括首次连接和重连 之后调用的函数,
111
+ 比如可以重新调用一些函数,仅连接发起方有效 */
99
112
  on_connected?(this: Remote): void;
100
113
  }
101
114
  /** 通过创建 remote 对象对 websocket rpc 进行抽象
@@ -120,8 +133,8 @@ export declare class Remote {
120
133
  url?: string;
121
134
  /** 能被对端调用的函数 */
122
135
  funcs: Record<string, MessageHandler>;
123
- /** `false` 是否启用主动探测连接,在连接状态下以 30s 间隔发送心跳包确保连接状态 */
124
- probe: boolean;
136
+ /** tcp keep alive */
137
+ alive: boolean;
125
138
  /** websocket 连接建立成功时调用对端 register 函数的参数 (仅发起方有效) */
126
139
  args?: any[];
127
140
  /** `true` 是否打印连接信息、错误信息 */
@@ -133,8 +146,6 @@ export declare class Remote {
133
146
  /** map<id, message handler>: 通过 (rpc message).id 找到对应的 handler
134
147
  一元 rpc 接收方不需要设置 handlers, 发送方需要 */
135
148
  handlers: Map<number, MessageHandler<any>>;
136
- /** 是否正在定时主动检测重连 */
137
- probing: boolean;
138
149
  /** websocket 检测到错误,_on_error 被调用,此时会尝试一段时间后重连 */
139
150
  reconnecting: NodeJS.Timeout;
140
151
  /** 用户是否手动调用了 disconnect() 主动断开了连接 (仅发起方有效) */
@@ -143,7 +154,7 @@ export declare class Remote {
143
154
  error: WebSocketConnectionError | Error;
144
155
  /** 作为 websocket 连接发起方,传入 url
145
156
  作为 websocket 连接接收方,传入 websocket + name */
146
- constructor({ name, url, websocket, funcs, print, verbose, probe, args, on_error, on_reconnect, on_connected }?: RemoteOptions);
157
+ constructor({ name, url, websocket, funcs, print, verbose, alive, args, on_error, on_reconnect, on_connected }?: RemoteOptions);
147
158
  /** 统一处理首次连接和连接后的 websocket 错误 */
148
159
  _on_error: (error: WebSocketConnectionError | Error) => void;
149
160
  on_reconnect?: (this: Remote) => Promise<void>;
@@ -168,13 +179,13 @@ export declare class Remote {
168
179
  /** 尝试建立连接,通常用于开始保活
169
180
  重连错误会在 this.connect 里面调用 this._on_error 处理 */
170
181
  try_connect(): Promise<void>;
171
- /** 开始心跳保活 */
172
- probe_connection(print_timeout?: boolean): Promise<void>;
173
182
  /** 检测连接,返回连接错误,出错时触发 on_error 打印错误信息
174
183
  返回值:
175
184
  - 连接正常返回: undefined
176
185
  - 连接错误返回: 实际的连接错误,通常是 WebSocketConnectionError | TimeoutError */
177
186
  test(print_timeout?: boolean): Promise<WebSocketConnectionError | TimeoutError | Error>;
187
+ /** node.js 下连接接收方在 Remote 创建后手动启用 tcp keep alive */
188
+ keep_alive(): void;
178
189
  /** 手动关闭到对端的 websocket 连接 */
179
190
  disconnect(): void;
180
191
  /** 发送 message 到对端 remote
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, defer2, delay, genid, Lock, nowstr, set_error_message, timeout, TimeoutError } from "./utils.common.js";
4
+ import { check, defer, defer2, 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([
@@ -94,6 +94,7 @@ let websocket_proxy_agents = {};
94
94
  - protocols?
95
95
  - max_payload?: `8 gb` (仅 nodejs 环境有效)
96
96
  - proxy?: string (仅 nodejs 环境有效)
97
+ - keep_alive_duration?: 毫秒数,设置后启用操作系统级的 keep alive (仅 nodejs 环境可以有效,浏览器端默认已启用)
97
98
  - on_message: 根据 websocket frame 的 opcode 不同 (text frame 或 binary frame),event 中的 data 对应为 ArrayBuffer 或者 string
98
99
  https://datatracker.ietf.org/doc/html/rfc6455#section-5.2
99
100
  - on_error?: 在 websocket 出错和非正常关闭 (close, error 事件) 时都调用,可以根据 error.type 来区分,error 的类型是 WebSocketConnectionError,
@@ -106,7 +107,7 @@ export async function connect_websocket(url, { print = {
106
107
  error: true,
107
108
  close: true
108
109
  }, protocols, max_payload = 2 ** 33, // 8 GB
109
- proxy, on_message, on_error, on_close, connect }) {
110
+ proxy, keep_alive_duration, on_message, on_error, on_close, connect }) {
110
111
  const { nodejs } = platform;
111
112
  if (typeof print === 'boolean')
112
113
  print = {
@@ -114,6 +115,8 @@ proxy, on_message, on_error, on_close, connect }) {
114
115
  error: print,
115
116
  close: print
116
117
  };
118
+ if (keep_alive_duration)
119
+ check(nodejs, 'keep_alive_duration 仅 nodejs 环境有效');
117
120
  let websocket = new (await platform.get_websocket())(url, protocols,
118
121
  // @ts-ignore
119
122
  nodejs ?
@@ -136,6 +139,8 @@ proxy, on_message, on_error, on_close, connect }) {
136
139
  console.log(websocket.url +
137
140
  (websocket.protocol ? ' ' + websocket.protocol.bracket() : '') +
138
141
  t(' 已连接'));
142
+ if (keep_alive_duration)
143
+ websocket._socket.setKeepAlive(true, keep_alive_duration);
139
144
  pwebsocket.resolve(websocket);
140
145
  }, { once: true });
141
146
  // websocket error, close 事件只选一个最详细的构造 WebSocketConnectionError 并调用 on_error
@@ -200,8 +205,8 @@ export class Remote {
200
205
  url;
201
206
  /** 能被对端调用的函数 */
202
207
  funcs;
203
- /** `false` 是否启用主动探测连接,在连接状态下以 30s 间隔发送心跳包确保连接状态 */
204
- probe = false;
208
+ /** tcp keep alive */
209
+ alive = false;
205
210
  /** websocket 连接建立成功时调用对端 register 函数的参数 (仅发起方有效) */
206
211
  args;
207
212
  /** `true` 是否打印连接信息、错误信息 */
@@ -214,8 +219,6 @@ export class Remote {
214
219
  /** map<id, message handler>: 通过 (rpc message).id 找到对应的 handler
215
220
  一元 rpc 接收方不需要设置 handlers, 发送方需要 */
216
221
  handlers = new Map();
217
- /** 是否正在定时主动检测重连 */
218
- probing = false;
219
222
  /** websocket 检测到错误,_on_error 被调用,此时会尝试一段时间后重连 */
220
223
  reconnecting;
221
224
  /** 用户是否手动调用了 disconnect() 主动断开了连接 (仅发起方有效) */
@@ -224,9 +227,13 @@ export class Remote {
224
227
  error;
225
228
  /** 作为 websocket 连接发起方,传入 url
226
229
  作为 websocket 连接接收方,传入 websocket + name */
227
- constructor({ name, url, websocket, funcs, print, verbose, probe, args, on_error, on_reconnect, on_connected } = {}) {
230
+ constructor({ name, url, websocket, funcs, print, verbose, alive, args, on_error, on_reconnect, on_connected } = {}) {
228
231
  if (name)
229
232
  this.name = name;
233
+ if (alive) {
234
+ check(!platform.browser, '浏览器端有默认 tcp keep alive 心跳机制,禁止设置 alive 选项');
235
+ this.alive = true;
236
+ }
230
237
  if (url) {
231
238
  check(!websocket, '构建 Remote 时 url 和 websocket 只能传其中一个');
232
239
  this.url = url;
@@ -237,8 +244,10 @@ export class Remote {
237
244
  }
238
245
  else { // 连接接收方,一定是 nodejs 环境
239
246
  check(websocket, '构建 Remote 时需传入 url 或者 websocket');
240
- this.lwebsocket.resource = websocket;
241
247
  websocket.binaryType = 'arraybuffer';
248
+ if (this.alive)
249
+ websocket._socket.setKeepAlive(true, 30_000);
250
+ this.lwebsocket.resource = websocket;
242
251
  // 参考 connect_websocket 实现
243
252
  let errored;
244
253
  const on_close_or_error = (event) => {
@@ -265,8 +274,6 @@ export class Remote {
265
274
  check(!funcs.echo);
266
275
  this.funcs = funcs;
267
276
  }
268
- if (probe !== undefined)
269
- this.probe = probe;
270
277
  if (args)
271
278
  this.args = args;
272
279
  if (print !== undefined)
@@ -287,7 +294,7 @@ export class Remote {
287
294
  if (error instanceof WebSocketConnectionError &&
288
295
  !this.reconnecting &&
289
296
  this.url &&
290
- (this.funcs || this.probe)) {
297
+ this.funcs) {
291
298
  this.reconnecting = setTimeout(this.reconnect, this.error ? 20_000 : 2_000);
292
299
  this.error = error;
293
300
  }
@@ -335,9 +342,6 @@ export class Remote {
335
342
  async connect() {
336
343
  if (this.disconnected)
337
344
  throw new Error(`remote (${this.name || this.url}) 已调用过 disconnect 断开连接,无法再次 connect`);
338
- // 首次 connect 开始探测
339
- if (this.probe && !this.probing)
340
- this.probe_connection();
341
345
  if (this.check_connection())
342
346
  return;
343
347
  try {
@@ -363,7 +367,8 @@ export class Remote {
363
367
  this.lwebsocket.resource = await connect_websocket(this.url, {
364
368
  on_message: this._on_message,
365
369
  on_error: this._on_error,
366
- print: this.print
370
+ print: this.print,
371
+ keep_alive_duration: this.alive ? 30_000 : undefined
367
372
  });
368
373
  this.error = null;
369
374
  if (this.args)
@@ -378,21 +383,6 @@ export class Remote {
378
383
  }
379
384
  catch { }
380
385
  }
381
- /** 开始心跳保活 */
382
- async probe_connection(print_timeout = true) {
383
- // 手动调用该函数时也会启用 probe
384
- this.probe = true;
385
- this.probing = true;
386
- for (let timeouted = false;;) {
387
- await delay(timeouted ? 5_000 : 30_000);
388
- if (this.disconnected || !this.url && !this.check_connection() || !this.probe)
389
- break;
390
- if (this.reconnecting)
391
- continue;
392
- // 产生的非 TimeoutError 应该都通过 _on_error 输出了,同时可能触发了重连
393
- timeouted = (await this.test(print_timeout)) instanceof TimeoutError;
394
- }
395
- }
396
386
  /** 检测连接,返回连接错误,出错时触发 on_error 打印错误信息
397
387
  返回值:
398
388
  - 连接正常返回: undefined
@@ -416,6 +406,12 @@ export class Remote {
416
406
  return error;
417
407
  }
418
408
  }
409
+ /** node.js 下连接接收方在 Remote 创建后手动启用 tcp keep alive */
410
+ keep_alive() {
411
+ check(!this.url && platform.nodejs);
412
+ this.alive = true;
413
+ this.lwebsocket.resource?._socket.setKeepAlive(true, 30_000);
414
+ }
419
415
  /** 手动关闭到对端的 websocket 连接 */
420
416
  disconnect() {
421
417
  this.disconnected = true;
package/net.d.ts CHANGED
@@ -114,6 +114,7 @@ export interface ConnectOptions {
114
114
  local_port?: number;
115
115
  timeout?: number;
116
116
  on_timeout?: OnTimeout;
117
+ keep_alive_duration?: number;
117
118
  print?: {
118
119
  error: boolean;
119
120
  connect: boolean;
@@ -127,8 +128,9 @@ export interface ConnectOptions {
127
128
  - options?:
128
129
  - local_port?: `随机端口` 使用的本地端口
129
130
  - timeout?: `2000` 超时时间
131
+ - keep_alive_duration?: 毫秒数,设置后启用操作系统级的 keep alive
130
132
  - print?: 打印连接日志,错误日志
131
133
  - error?: `true`
132
134
  - connect: `false` */
133
- export declare function connect(hostname: string, port: number, { local_port, timeout: _timeout, on_timeout, print }?: ConnectOptions): Deferred2<net.Socket>;
135
+ export declare function connect(hostname: string, port: number, { local_port, timeout: _timeout, on_timeout, keep_alive_duration, print }?: ConnectOptions): Deferred2<net.Socket>;
134
136
  export declare function get_socket_ip(socket: net.Socket): string;
package/net.js CHANGED
@@ -301,10 +301,11 @@ export async function request_json(url, options) {
301
301
  - options?:
302
302
  - local_port?: `随机端口` 使用的本地端口
303
303
  - timeout?: `2000` 超时时间
304
+ - keep_alive_duration?: 毫秒数,设置后启用操作系统级的 keep alive
304
305
  - print?: 打印连接日志,错误日志
305
306
  - error?: `true`
306
307
  - connect: `false` */
307
- export function connect(hostname, port, { local_port, timeout: _timeout = 2000, on_timeout, print = { error: true, connect: false } } = {}) {
308
+ export function connect(hostname, port, { local_port, timeout: _timeout = 2000, on_timeout, keep_alive_duration, print = { error: true, connect: false } } = {}) {
308
309
  let pconnected = defer2();
309
310
  let timeouted = false;
310
311
  function get_message(message) {
@@ -314,7 +315,9 @@ export function connect(hostname, port, { local_port, timeout: _timeout = 2000,
314
315
  host: hostname,
315
316
  port,
316
317
  localPort: local_port,
317
- noDelay: true
318
+ noDelay: true,
319
+ keepAlive: Boolean(keep_alive_duration),
320
+ keepAliveInitialDelay: keep_alive_duration
318
321
  }, () => {
319
322
  if (pconnected.settled) {
320
323
  if (print)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xshell",
3
- "version": "1.3.8",
3
+ "version": "1.3.9",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "bin": {
@@ -76,9 +76,9 @@
76
76
  "mime-types": "^3.0.1",
77
77
  "p-map": "^7.0.4",
78
78
  "react": "^19.2.0",
79
- "react-i18next": "^16.3.4",
79
+ "react-i18next": "^16.3.5",
80
80
  "resolve-path": "^1.4.0",
81
- "sass": "^1.94.1",
81
+ "sass": "^1.94.2",
82
82
  "sass-loader": "^16.0.6",
83
83
  "source-map-loader": "^5.0.0",
84
84
  "strip-ansi": "^7.1.2",
package/utils.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Writable, Transform, type Readable, type Duplex, type TransformCallback } from 'node:stream';
1
+ import { Writable, Transform, type Readable, type TransformCallback } from 'node:stream';
2
2
  import util from 'node:util';
3
3
  import './prototype.ts';
4
4
  import './platform.ts';
@@ -31,19 +31,8 @@ export declare namespace inspect {
31
31
  const custom: typeof util.inspect.custom;
32
32
  const defaultOptions: util.InspectOptions;
33
33
  }
34
- /** npm map-stream
35
- filter will reemit the data if cb(err,pass) pass is truthy
36
-
37
- reduce is more tricky
38
- maybe we want to group the reductions or emit progress updates occasionally
39
- the most basic reduce just emits one 'data' event after it has recieved 'end'
40
-
41
- create an event stream and apply function to each .write,
42
- emitting each response as data unless it's an empty callback
43
- */
44
- export declare function map_stream<Out, In = any>(mapper: (obj: In, cb: Function) => any, options?: {
45
- failures?: boolean;
46
- }): Duplex;
34
+ /** 消费一个可读流 */
35
+ export declare function consume_stream(stream: Readable, ignore_error?: boolean): Promise<void>;
47
36
  export declare function stream_to_lines(stream: Readable): AsyncGenerator<string, void, unknown>;
48
37
  export declare class WritableMemoryStream extends Writable {
49
38
  chunks: Uint8Array[];
@@ -65,8 +54,6 @@ export declare class DecoderStream extends Transform {
65
54
  _transform(chunk: Uint8Array, encoding: BufferEncoding, callback: TransformCallback): void;
66
55
  _flush(callback: TransformCallback): void;
67
56
  }
68
- /** 消费一个可读流 */
69
- export declare function consume_stream(stream: Readable, ignore_error?: boolean): Promise<void>;
70
57
  /** 根据 range 生成整数序列 (iterable)
71
58
  - range: 取值为逗号分割的多个可用值或值区间 (不能含有空格),比如:`8321,8322,8300-8310,11000-11999`
72
59
  - reverse?: `false` 在 range 内从后往前生成 */
package/utils.js CHANGED
@@ -1,4 +1,4 @@
1
- import { Stream, Writable, Transform } from 'node:stream';
1
+ import { Writable, Transform } from 'node:stream';
2
2
  import util from 'node:util';
3
3
  import ncrypto from 'node:crypto';
4
4
  import "./prototype.js";
@@ -94,120 +94,16 @@ export function colored(str, color, enabled = inspect.defaultOptions.colors) {
94
94
  inspect.defaultOptions = util.inspect.defaultOptions;
95
95
  })(inspect || (inspect = {}));
96
96
  // ------------------------------------ stream
97
- /** npm map-stream
98
- filter will reemit the data if cb(err,pass) pass is truthy
99
-
100
- reduce is more tricky
101
- maybe we want to group the reductions or emit progress updates occasionally
102
- the most basic reduce just emits one 'data' event after it has recieved 'end'
103
-
104
- create an event stream and apply function to each .write,
105
- emitting each response as data unless it's an empty callback
106
- */
107
- export function map_stream(mapper, options) {
108
- options = options || {};
109
- let inputs = 0, outputs = 0, ended = false, paused = false, destroyed = false, last_written = 0, in_next = false;
110
- let stream = Object.assign(new Stream(), {
111
- readable: true,
112
- writable: true,
113
- write(data) {
114
- if (ended)
115
- throw new Error('map stream is not writable');
116
- in_next = false;
117
- inputs++;
118
- try {
119
- // catch sync errors and handle them like async errors
120
- const written = wrapped_mapper(data, inputs, next);
121
- paused = (written === false);
122
- return !paused;
123
- }
124
- catch (err) {
125
- // if the callback has been called syncronously, and the error has occured in an listener, throw it again.
126
- if (in_next)
127
- throw err;
128
- next(err);
129
- return !paused;
130
- }
131
- },
132
- end(data) {
133
- if (ended)
134
- return;
135
- _end(data);
136
- },
137
- destroy() {
138
- ended = destroyed = true;
139
- stream.writable = stream.readable = paused = false;
140
- process.nextTick(function () {
141
- stream.emit('close');
142
- });
143
- },
144
- pause() {
145
- paused = true;
146
- },
147
- resume() {
148
- paused = false;
149
- }
150
- });
151
- let error_event_name = options.failures ? 'failure' : 'error';
152
- // Items that are not ready to be written yet (because they would come out of order) get stuck in a queue for later.
153
- let write_queue = {};
154
- function queue_data(data, number) {
155
- let next_to_write = last_written + 1;
156
- if (number === next_to_write) {
157
- // If it's next, and its not undefined write it
158
- if (data !== undefined)
159
- stream.emit('data', data);
160
- last_written++;
161
- next_to_write++;
162
- }
163
- else
164
- // Otherwise queue it for later.
165
- write_queue[number] = data;
166
- // If the next value is in the queue, write it
167
- if (Object.prototype.hasOwnProperty.call(write_queue, next_to_write)) {
168
- let data_to_write = write_queue[next_to_write];
169
- delete write_queue[next_to_write];
170
- return queue_data(data_to_write, next_to_write);
171
- }
172
- outputs++;
173
- if (inputs === outputs) {
174
- if (paused) {
175
- paused = false;
176
- stream.emit('drain'); // written all the incoming events
177
- }
178
- if (ended)
179
- _end();
180
- }
181
- }
182
- function next(err, data, number) {
183
- if (destroyed)
184
- return;
185
- in_next = true;
186
- if (!err || options.failures)
187
- queue_data(data, number);
188
- if (err)
189
- stream.emit(error_event_name, err);
190
- in_next = false;
191
- }
192
- /** Wrap the mapper function by calling its callback with the order number of the item in the stream. */
193
- function wrapped_mapper(input, number, callback) {
194
- return mapper.call(null, input, function (err, data) {
195
- callback(err, data, number);
196
- });
97
+ /** 消费一个可读流 */
98
+ export async function consume_stream(stream, ignore_error = false) {
99
+ try {
100
+ for await (const chunk of stream)
101
+ ;
197
102
  }
198
- function _end(data) {
199
- // if end was called with args, write it,
200
- ended = true; // write will emit 'end' if ended is true
201
- stream.writable = false;
202
- if (data !== undefined)
203
- return queue_data(data, inputs);
204
- else if (inputs === outputs) { // wait for processing
205
- stream.readable = false;
206
- stream.emit('end');
207
- stream.destroy();
208
- }
103
+ catch (error) {
104
+ if (!ignore_error)
105
+ throw error;
209
106
  }
210
- return stream;
211
107
  }
212
108
  export async function* stream_to_lines(stream) {
213
109
  let buf = '';
@@ -269,17 +165,6 @@ export class DecoderStream extends Transform {
269
165
  callback();
270
166
  }
271
167
  }
272
- /** 消费一个可读流 */
273
- export async function consume_stream(stream, ignore_error = false) {
274
- try {
275
- for await (const chunk of stream)
276
- ;
277
- }
278
- catch (error) {
279
- if (!ignore_error)
280
- throw error;
281
- }
282
- }
283
168
  /** 根据 range 生成整数序列 (iterable)
284
169
  - range: 取值为逗号分割的多个可用值或值区间 (不能含有空格),比如:`8321,8322,8300-8310,11000-11999`
285
170
  - reverse?: `false` 在 range 内从后往前生成 */