xshell 1.1.13 → 1.1.14
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 +2 -0
- package/builder.js +2 -0
- package/net.browser.d.ts +1 -1
- package/net.d.ts +9 -14
- package/net.js +57 -104
- package/package.json +1 -1
- package/path.d.ts +2 -2
- package/process.d.ts +6 -4
- package/process.js +23 -23
- package/prototype.browser.d.ts +4 -0
- package/prototype.browser.js +6 -0
- package/prototype.d.ts +4 -0
- package/prototype.js +9 -5
- package/utils.browser.d.ts +4 -2
- package/utils.browser.js +9 -4
- package/utils.d.ts +7 -2
- package/utils.js +14 -4
package/builder.d.ts
CHANGED
|
@@ -140,7 +140,9 @@ export declare class Bundler {
|
|
|
140
140
|
build(print?: boolean): Promise<void>;
|
|
141
141
|
close(): Promise<void>;
|
|
142
142
|
build_all(print?: boolean): Promise<void>;
|
|
143
|
+
/** 打包构建 js, 构建 html, 复制依赖文件 */
|
|
143
144
|
build_all_and_close(print?: boolean): Promise<void>;
|
|
145
|
+
/** 仅打包构建 js, 不复制依赖 */
|
|
144
146
|
build_and_close(print?: boolean): Promise<void>;
|
|
145
147
|
build_htmls(print?: {
|
|
146
148
|
info: boolean;
|
package/builder.js
CHANGED
|
@@ -489,6 +489,7 @@ export class Bundler {
|
|
|
489
489
|
this.target === 'web' && this.htmls && this.build_htmls({ info: print, files: false })
|
|
490
490
|
]);
|
|
491
491
|
}
|
|
492
|
+
/** 打包构建 js, 构建 html, 复制依赖文件 */
|
|
492
493
|
async build_all_and_close(print = true) {
|
|
493
494
|
await Promise.all([
|
|
494
495
|
this.build_and_close(print),
|
|
@@ -496,6 +497,7 @@ export class Bundler {
|
|
|
496
497
|
this.target === 'web' && this.htmls && this.build_htmls({ info: print, files: false })
|
|
497
498
|
]);
|
|
498
499
|
}
|
|
500
|
+
/** 仅打包构建 js, 不复制依赖 */
|
|
499
501
|
async build_and_close(print = true) {
|
|
500
502
|
await this.build(print);
|
|
501
503
|
await this.close();
|
package/net.browser.d.ts
CHANGED
|
@@ -66,7 +66,7 @@ export declare function request(url: string | URL, options: RequestOptions): Pro
|
|
|
66
66
|
/** 发起 http 请求并将响应体作为 json 解析 */
|
|
67
67
|
export declare function request_json<T = any>(url: string, options?: RequestOptions): Promise<T>;
|
|
68
68
|
export declare class WebSocketConnectionError extends Error {
|
|
69
|
-
name:
|
|
69
|
+
name: "WebSocketConnectionError";
|
|
70
70
|
url: string;
|
|
71
71
|
protocols?: string[];
|
|
72
72
|
websocket: WebSocket;
|
package/net.d.ts
CHANGED
|
@@ -71,6 +71,13 @@ export interface RequestError extends Error {
|
|
|
71
71
|
response?: FullResponse<string>;
|
|
72
72
|
[inspect.custom]: Function;
|
|
73
73
|
}
|
|
74
|
+
export interface StatusCodeError {
|
|
75
|
+
status: number;
|
|
76
|
+
}
|
|
77
|
+
export declare class StatusCodeError extends Error {
|
|
78
|
+
name: "StatusCodeError";
|
|
79
|
+
constructor(status: number, url: string);
|
|
80
|
+
}
|
|
74
81
|
/**
|
|
75
82
|
- url: 必须是完整 url
|
|
76
83
|
- options?:
|
|
@@ -91,7 +98,7 @@ export interface RequestError extends Error {
|
|
|
91
98
|
- encoding?: `根据网页 content-type: charset=gb18030 提取 || 'utf-8'` 传入 'binary' 时返回 Buffer
|
|
92
99
|
(只对非 raw 的请求起作用)
|
|
93
100
|
- retries?: `false` 可以传入 true (默认 2 次) 或 重试次数
|
|
94
|
-
- timeout?: `5 * 1000` 超时后会抛出 error.name 为 'TimeoutError' 的 error, 可以传入 0 来禁用超时
|
|
101
|
+
- timeout?: `5 * 1000` 超时后会抛出 error.name 为 'TimeoutError' 的 error (但类型不是 utils.ts 中的 TimeoutError), 可以传入 0 来禁用超时
|
|
95
102
|
- auth?: BasicAuth | BearerAuth
|
|
96
103
|
- cookies?: 需要额外添加到请求的 cookies, 默认情况下携带了 MemoryCookieStore 中保存的之前 http 响应中的 cookies
|
|
97
104
|
- raw?: `false` 传入后返回整个 response (RawResponse),body 为 Readable
|
|
@@ -112,20 +119,8 @@ export declare function request(url: string | URL, options: RequestOptions & {
|
|
|
112
119
|
export declare function request(url: string | URL, options: RequestOptions): Promise<string>;
|
|
113
120
|
/** 发起 http 请求并将响应体作为 json 解析 */
|
|
114
121
|
export declare function request_json<T = any>(url: string | URL, options?: RequestOptions): Promise<T>;
|
|
115
|
-
/** post json to http://localhost:8421/api/rpc
|
|
116
|
-
- func: function name
|
|
117
|
-
- args?: argument array
|
|
118
|
-
- options?:
|
|
119
|
-
- ignore?: `false` wait for execution but do not serialize result to response
|
|
120
|
-
- async?: `false` do not wait for exec
|
|
121
|
-
*/
|
|
122
|
-
export declare function rpc(func: string, args?: any[], { url, async: _async, ignore }?: {
|
|
123
|
-
url?: string;
|
|
124
|
-
async?: boolean;
|
|
125
|
-
ignore?: boolean;
|
|
126
|
-
}): Promise<any>;
|
|
127
122
|
export declare class WebSocketConnectionError extends Error {
|
|
128
|
-
name:
|
|
123
|
+
name: "WebSocketConnectionError";
|
|
129
124
|
url: string;
|
|
130
125
|
protocols?: string[];
|
|
131
126
|
event: CloseEvent | ErrorEvent;
|
package/net.js
CHANGED
|
@@ -3,7 +3,7 @@ import { buffer as stream_to_buffer, text as stream_to_text } from 'stream/consu
|
|
|
3
3
|
import { isReadable } from 'stream';
|
|
4
4
|
import { t } from "./i18n/instance.js";
|
|
5
5
|
import "./prototype.js";
|
|
6
|
-
import { inspect, concat, assert, genid, delay, Lock, encode, decode, pipe_with_error, map_values, unique, timeout, check } from "./utils.js";
|
|
6
|
+
import { inspect, concat, assert, genid, delay, Lock, encode, decode, pipe_with_error, map_values, unique, timeout, check, colored } from "./utils.js";
|
|
7
7
|
export const WebSocketConnecting = 0;
|
|
8
8
|
export const WebSocketOpen = 1;
|
|
9
9
|
export const WebSocketClosing = 2;
|
|
@@ -57,16 +57,27 @@ async function request_retry(url, options, _timeout, retries = 0, count = 0, pri
|
|
|
57
57
|
if (count < retries) {
|
|
58
58
|
const duration = 2 ** count;
|
|
59
59
|
if (print.retry)
|
|
60
|
-
console.log(`${
|
|
60
|
+
console.log(`${`等待 ${duration} 秒后重试请求 (已尝试 ${count + 1} 次) ··`.yellow} ${url.toString().blue.underline}`);
|
|
61
61
|
await delay(1000 * duration);
|
|
62
62
|
return request_retry(url, options, _timeout, retries, count + 1, print);
|
|
63
63
|
}
|
|
64
|
-
else
|
|
65
|
-
|
|
64
|
+
else {
|
|
65
|
+
const seconds = _timeout / 1000;
|
|
66
|
+
throw Object.assign(new Error(`请求超过 ${seconds.toFixed(seconds < 1 ? 1 : 0)} 秒等待时间: ${url.toString()}`), { name: 'TimeoutError' });
|
|
67
|
+
}
|
|
66
68
|
else
|
|
67
69
|
throw error;
|
|
68
70
|
}
|
|
69
71
|
}
|
|
72
|
+
export class StatusCodeError extends Error {
|
|
73
|
+
name = 'StatusCodeError';
|
|
74
|
+
constructor(status, url) {
|
|
75
|
+
super(`状态码 ${status}: ${url}`);
|
|
76
|
+
Object.defineProperties(this, {
|
|
77
|
+
status: { value: status }
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
70
81
|
export async function request(url, options = {}) {
|
|
71
82
|
let { default: undici, ProxyAgent: UndiciProxyAgent, FormData } = await import('undici');
|
|
72
83
|
UndiciProxyAgent ??= undici.ProxyAgent;
|
|
@@ -117,11 +128,11 @@ export async function request(url, options = {}) {
|
|
|
117
128
|
headers.cookie = request_cookies.map(cookie => cookie.cookieString())
|
|
118
129
|
.join('; ');
|
|
119
130
|
if (_headers) {
|
|
120
|
-
|
|
131
|
+
check(Object.getPrototypeOf(_headers)?.constructor.name !== 'Headers');
|
|
121
132
|
for (const key in _headers)
|
|
122
133
|
// 可能在 http/2 的 response 中会有这样开头的保留 headers, 在透传时忽略比较好
|
|
123
134
|
if (!key.startsWith(':') && !key.startsWith('sec-') && !drop_request_headers.has(key)) {
|
|
124
|
-
|
|
135
|
+
check(key === key.toLowerCase(), `传入 request 的 headers 参数中 key 应该都是小写的,实际为 ${key}`);
|
|
125
136
|
headers[key] = _headers[key];
|
|
126
137
|
}
|
|
127
138
|
}
|
|
@@ -142,9 +153,7 @@ export async function request(url, options = {}) {
|
|
|
142
153
|
return dispatcher;
|
|
143
154
|
})();
|
|
144
155
|
})(),
|
|
145
|
-
//
|
|
146
|
-
maxRedirections: redirect === 'follow' ? 5 : 0,
|
|
147
|
-
// 下面这些 timeout 都不是总的时间,没法用
|
|
156
|
+
// 下面这些 timeout 都不是总的时间
|
|
148
157
|
headersTimeout: timeout,
|
|
149
158
|
// 从收完 headers 开始算
|
|
150
159
|
bodyTimeout: timeout,
|
|
@@ -214,7 +223,7 @@ export async function request(url, options = {}) {
|
|
|
214
223
|
body = pipe_with_error(_body, zlib.createBrotliDecompress());
|
|
215
224
|
break;
|
|
216
225
|
default:
|
|
217
|
-
throw new Error(
|
|
226
|
+
throw new Error(`不支持 content-encoding: ${content_encoding.quote()} 的 http 请求`);
|
|
218
227
|
}
|
|
219
228
|
}
|
|
220
229
|
response = {
|
|
@@ -223,85 +232,49 @@ export async function request(url, options = {}) {
|
|
|
223
232
|
body
|
|
224
233
|
};
|
|
225
234
|
if (!((200 <= status && status <= 299) || status === 304 || (redirect === 'manual' && 300 <= status && status < 400)))
|
|
226
|
-
throw
|
|
235
|
+
throw new StatusCodeError(status, url.toString());
|
|
227
236
|
}
|
|
228
237
|
catch (error) {
|
|
229
|
-
;
|
|
230
|
-
error
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
let _method = method || 'GET';
|
|
241
|
-
if (colors)
|
|
242
|
-
_method = _method.red;
|
|
243
|
-
let _url = urlstr;
|
|
244
|
-
if (colors)
|
|
245
|
-
_url = _url.blue.underline;
|
|
246
|
-
let s = '\n' +
|
|
247
|
-
`${_method} ${_url}\n`;
|
|
248
|
-
if (queries && Object.keys(queries).length) {
|
|
249
|
-
let _query = t('请求参数:');
|
|
250
|
-
if (colors)
|
|
251
|
-
_query = _query.yellow;
|
|
252
|
-
s += _query + '\n' +
|
|
253
|
-
inspect(queries, options) + '\n';
|
|
254
|
-
}
|
|
255
|
-
if (body !== undefined) {
|
|
256
|
-
let _body = t('请求体:');
|
|
257
|
-
if (colors)
|
|
258
|
-
_body = _body.yellow;
|
|
259
|
-
s += _body + '\n' +
|
|
260
|
-
inspect(body, options) + '\n';
|
|
261
|
-
}
|
|
262
|
-
if (error.name === 'StatusCodeError') {
|
|
263
|
-
let _status = t('响应状态码:');
|
|
264
|
-
if (colors)
|
|
265
|
-
_status = _status.yellow;
|
|
266
|
-
let _code = String(response.status);
|
|
267
|
-
if (colors)
|
|
268
|
-
_code = _code.red;
|
|
269
|
-
s += _status + ' ' + _code + '\n';
|
|
270
|
-
}
|
|
271
|
-
else if (error.name === 'TimeoutError') {
|
|
272
|
-
let _timeout = t('超过等待时间:');
|
|
273
|
-
if (colors)
|
|
274
|
-
_timeout = _timeout.red;
|
|
275
|
-
s += `${_timeout} ${timeout} ms\n`;
|
|
276
|
-
}
|
|
277
|
-
if (response) {
|
|
278
|
-
let _headers = t('响应头:');
|
|
279
|
-
if (colors)
|
|
280
|
-
_headers = _headers.yellow;
|
|
281
|
-
s += _headers + '\n';
|
|
282
|
-
for (const key in response.headers) {
|
|
283
|
-
const value = response.headers[key];
|
|
284
|
-
s += `${key}: ${value}\n`;
|
|
238
|
+
response ??= error.response;
|
|
239
|
+
throw Object.defineProperties(error, {
|
|
240
|
+
url: { value: url },
|
|
241
|
+
options: { value: options },
|
|
242
|
+
...response ? {
|
|
243
|
+
response: {
|
|
244
|
+
value: {
|
|
245
|
+
status: response.status,
|
|
246
|
+
headers: response.headers,
|
|
247
|
+
body: await stream_to_text(response.body),
|
|
248
|
+
}
|
|
285
249
|
}
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
250
|
+
} : {},
|
|
251
|
+
[inspect.custom]: {
|
|
252
|
+
value(depth, options, inspect) {
|
|
253
|
+
const { colors } = options;
|
|
254
|
+
const c = (str, color) => colored(str, color, colors);
|
|
255
|
+
let s = '\n' +
|
|
256
|
+
`${c(method || 'GET', 'red')} ${c(c(urlstr, 'blue'), 'underline')}\n`;
|
|
257
|
+
if (queries && Object.keys(queries).length)
|
|
258
|
+
s += c('请求参数:\n', 'yellow') +
|
|
259
|
+
inspect(queries, options).ensure_end();
|
|
260
|
+
if (body !== undefined)
|
|
261
|
+
s += c('请求体:\n', 'yellow') +
|
|
262
|
+
inspect(body, options).ensure_end();
|
|
263
|
+
if (response) {
|
|
264
|
+
s += c('响应头:\n', 'yellow');
|
|
265
|
+
for (const key in response.headers) {
|
|
266
|
+
const value = response.headers[key];
|
|
267
|
+
s += `${key}: ${value}\n`;
|
|
268
|
+
}
|
|
269
|
+
if (error.response.body)
|
|
270
|
+
s += c('响应体:\n', 'yellow') +
|
|
271
|
+
error.response.body.toString().ensure_end();
|
|
272
|
+
}
|
|
273
|
+
s += inspect(error, { ...options, customInspect: false });
|
|
274
|
+
return s;
|
|
292
275
|
}
|
|
293
276
|
}
|
|
294
|
-
|
|
295
|
-
if (colors)
|
|
296
|
-
_stack = _stack.yellow;
|
|
297
|
-
s += _stack + '\n';
|
|
298
|
-
if (error.cause)
|
|
299
|
-
s += inspect(error.cause, options) + '\n';
|
|
300
|
-
s += error.stack + '\n' +
|
|
301
|
-
'\n';
|
|
302
|
-
return s;
|
|
303
|
-
};
|
|
304
|
-
throw error;
|
|
277
|
+
});
|
|
305
278
|
}
|
|
306
279
|
if (raw)
|
|
307
280
|
return response;
|
|
@@ -337,26 +310,6 @@ export async function request_json(url, options) {
|
|
|
337
310
|
throw error;
|
|
338
311
|
}
|
|
339
312
|
}
|
|
340
|
-
// ------------------------------------ rpc client
|
|
341
|
-
/** post json to http://localhost:8421/api/rpc
|
|
342
|
-
- func: function name
|
|
343
|
-
- args?: argument array
|
|
344
|
-
- options?:
|
|
345
|
-
- ignore?: `false` wait for execution but do not serialize result to response
|
|
346
|
-
- async?: `false` do not wait for exec
|
|
347
|
-
*/
|
|
348
|
-
export async function rpc(func, args, { url = 'http://localhost:8421/api/rpc', async: _async = false, ignore = false } = {}) {
|
|
349
|
-
if (!func)
|
|
350
|
-
throw new Error('rpc argument error: no func');
|
|
351
|
-
return request_json(url, {
|
|
352
|
-
body: {
|
|
353
|
-
func,
|
|
354
|
-
args,
|
|
355
|
-
async: _async,
|
|
356
|
-
ignore,
|
|
357
|
-
}
|
|
358
|
-
});
|
|
359
|
-
}
|
|
360
313
|
export class WebSocketConnectionError extends Error {
|
|
361
314
|
name = 'WebSocketConnectionError';
|
|
362
315
|
// 这里不保留 websocket 引用,防止循环引用导致 JSON 序列化失败
|
package/package.json
CHANGED
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/process.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import type { InspectOptions } from 'util';
|
|
1
2
|
import { type ChildProcess } from 'child_process';
|
|
2
3
|
import './prototype.ts';
|
|
3
4
|
import type { Encoding } from './file.ts';
|
|
4
5
|
import type { MyProxy } from './net.ts';
|
|
5
|
-
import { inspect } from './utils.ts';
|
|
6
6
|
export declare const sea: boolean;
|
|
7
7
|
export declare const exe_nodejs: string;
|
|
8
8
|
export declare const platform: NodeJS.Platform;
|
|
@@ -103,8 +103,7 @@ export interface CallResult<TOutput extends string | Buffer = string> {
|
|
|
103
103
|
child: ChildProcess;
|
|
104
104
|
print: FullPrintOptions;
|
|
105
105
|
}
|
|
106
|
-
export
|
|
107
|
-
name: string;
|
|
106
|
+
export interface CallError<TOutput extends string | Buffer = string> extends Error {
|
|
108
107
|
pid: number;
|
|
109
108
|
stdout: TOutput;
|
|
110
109
|
stderr: TOutput;
|
|
@@ -113,8 +112,11 @@ export declare class CallError<TOutput extends string | Buffer = string> extends
|
|
|
113
112
|
command: string;
|
|
114
113
|
child: ChildProcess;
|
|
115
114
|
print: FullPrintOptions;
|
|
115
|
+
}
|
|
116
|
+
export declare class CallError<TOutput extends string | Buffer = string> extends Error {
|
|
117
|
+
name: "CallError";
|
|
116
118
|
constructor({ message, pid, stdout, stderr, code, signal, command, child, print }: CallResult<TOutput>);
|
|
117
|
-
[inspect.custom](): string;
|
|
119
|
+
[inspect.custom](depth: number, options: InspectOptions, inspect: Function): string;
|
|
118
120
|
}
|
|
119
121
|
/** 调用可执行文件,获取返回结果,错误时抛出 CallError
|
|
120
122
|
- exe: .exe 路径或文件名 (建议使用路径,跳过 path 搜索,性能更高)
|
package/process.js
CHANGED
|
@@ -2,14 +2,14 @@ import { spawn } from 'child_process';
|
|
|
2
2
|
import os from 'os';
|
|
3
3
|
import node_sea from 'node:sea';
|
|
4
4
|
import "./prototype.js";
|
|
5
|
-
import { inspect, DecoderStream, filter_values, check } from "./utils.js";
|
|
5
|
+
import { inspect, DecoderStream, filter_values, check, colored } from "./utils.js";
|
|
6
6
|
export const sea = node_sea.isSea();
|
|
7
7
|
export const exe_nodejs = process.execPath.fp;
|
|
8
8
|
export const platform = os.platform();
|
|
9
9
|
export const username = os.userInfo().username;
|
|
10
10
|
export const noprint = { print: false };
|
|
11
11
|
export const print_no_command = { print: { command: false, code: false, stdout: true, stderr: true } };
|
|
12
|
-
async function prepare_spawn(detached, exe, args, { cwd, window: _window
|
|
12
|
+
async function prepare_spawn(detached, exe, args, { cwd, window: _window, envs,
|
|
13
13
|
// @ts-ignore
|
|
14
14
|
input, fp_stdin, fp_stdout, fp_stderr, print = true, proxy,
|
|
15
15
|
// @ts-ignore
|
|
@@ -94,7 +94,7 @@ stdio }) {
|
|
|
94
94
|
cwd,
|
|
95
95
|
shell: false,
|
|
96
96
|
// processhacker 在 windowsHide 为 true 时不显示窗口
|
|
97
|
-
windowsHide: !
|
|
97
|
+
windowsHide: _window ?? Boolean(!detached || fp_stdout),
|
|
98
98
|
detached,
|
|
99
99
|
stdio,
|
|
100
100
|
...envs_ ? { env: envs_ } : {}
|
|
@@ -128,29 +128,29 @@ export async function start(exe, args = [], options = {}) {
|
|
|
128
128
|
}
|
|
129
129
|
export class CallError extends Error {
|
|
130
130
|
name = 'CallError';
|
|
131
|
-
pid;
|
|
132
|
-
stdout;
|
|
133
|
-
stderr;
|
|
134
|
-
code;
|
|
135
|
-
signal;
|
|
136
|
-
command;
|
|
137
|
-
child;
|
|
138
|
-
print;
|
|
139
131
|
constructor({ message, pid, stdout, stderr, code, signal, command, child, print }) {
|
|
140
132
|
super(message);
|
|
141
|
-
|
|
142
|
-
this
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
133
|
+
// defineProperty 默认 enumerable: false,不会在 inspect 中显示
|
|
134
|
+
Object.defineProperties(this, {
|
|
135
|
+
pid: { value: pid },
|
|
136
|
+
stdout: { value: stdout },
|
|
137
|
+
stderr: { value: stderr },
|
|
138
|
+
code: { value: code },
|
|
139
|
+
signal: { value: signal },
|
|
140
|
+
command: { value: command },
|
|
141
|
+
child: { value: child },
|
|
142
|
+
print: { value: print }
|
|
143
|
+
});
|
|
149
144
|
}
|
|
150
|
-
[inspect.custom]() {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
this.
|
|
145
|
+
[inspect.custom](depth, options, inspect) {
|
|
146
|
+
const { colors } = options;
|
|
147
|
+
return (!this.print.stdout && this.stdout
|
|
148
|
+
? `${colored('标准输出:\n', 'yellow', colors)}${this.stdout.toString().ensure_end()}`
|
|
149
|
+
: '') +
|
|
150
|
+
(!this.print.stderr && this.stderr
|
|
151
|
+
? `${colored('标准错误:\n', 'yellow', colors)}${this.stderr.toString().ensure_end()}`
|
|
152
|
+
: '') +
|
|
153
|
+
inspect(this, { ...options, customInspect: false });
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
156
|
export async function call(exe, args = [], options = {}) {
|
package/prototype.browser.d.ts
CHANGED
|
@@ -92,6 +92,10 @@ declare global {
|
|
|
92
92
|
strip_end(this: string, suffix: string, validate?: boolean): string;
|
|
93
93
|
/** 返回去掉 suffix 结尾的字符串,如果没有以 suffix 结尾则返回原字符串 */
|
|
94
94
|
strip_if_end(this: string, suffix: string): string;
|
|
95
|
+
/** 确保字符串以 prefix 开头,否则在头部追加 prefix */
|
|
96
|
+
ensure_start(this: string, prefix: string): string;
|
|
97
|
+
/** 确保字符串以 suffix (默认 '\n') 结尾,否则在尾部追加 suffix */
|
|
98
|
+
ensure_end(this: string, suffix?: string): string;
|
|
95
99
|
/** 从 search 字符串出现的位置开始截取到最后
|
|
96
100
|
- options?:
|
|
97
101
|
- include?: `false` 传 true 时包括 search 部分
|
package/prototype.browser.js
CHANGED
|
@@ -287,6 +287,12 @@ Object.defineProperties(String.prototype, {
|
|
|
287
287
|
strip_if_end(suffix) {
|
|
288
288
|
return this.endsWith(suffix) ? this.slice(0, -suffix.length) : this;
|
|
289
289
|
},
|
|
290
|
+
ensure_start(prefix) {
|
|
291
|
+
return this.startsWith(prefix) ? this : prefix + this;
|
|
292
|
+
},
|
|
293
|
+
ensure_end(suffix = '\n') {
|
|
294
|
+
return this.endsWith(suffix) ? this : this + suffix;
|
|
295
|
+
},
|
|
290
296
|
slice_from(search, { include = false, last = false } = {}) {
|
|
291
297
|
const i = last ? this.lastIndexOf(search) : this.indexOf(search);
|
|
292
298
|
if (i === -1)
|
package/prototype.d.ts
CHANGED
|
@@ -114,6 +114,10 @@ declare global {
|
|
|
114
114
|
strip_end(this: string, suffix: string, validate?: boolean): string;
|
|
115
115
|
/** 返回去掉 suffix 结尾的字符串,如果没有以 suffix 结尾则返回原字符串 */
|
|
116
116
|
strip_if_end(this: string, suffix: string): string;
|
|
117
|
+
/** 确保字符串以 prefix 开头,否则在头部追加 prefix */
|
|
118
|
+
ensure_start(this: string, prefix: string): string;
|
|
119
|
+
/** 确保字符串以 suffix (默认 '\n') 结尾,否则在尾部追加 suffix */
|
|
120
|
+
ensure_end(this: string, suffix?: string): string;
|
|
117
121
|
/** 从 search 字符串出现的位置开始截取到最后
|
|
118
122
|
- options?:
|
|
119
123
|
- include?: `false` 传 true 时包括 search 部分
|
package/prototype.js
CHANGED
|
@@ -309,6 +309,12 @@ if (!globalThis.my_prototype_defined) {
|
|
|
309
309
|
strip_if_end(suffix) {
|
|
310
310
|
return this.endsWith(suffix) ? this.slice(0, -suffix.length) : this;
|
|
311
311
|
},
|
|
312
|
+
ensure_start(prefix) {
|
|
313
|
+
return this.startsWith(prefix) ? this : prefix + this;
|
|
314
|
+
},
|
|
315
|
+
ensure_end(suffix = '\n') {
|
|
316
|
+
return this.endsWith(suffix) ? this : this + suffix;
|
|
317
|
+
},
|
|
312
318
|
slice_from(search, { include = false, last = false } = {}) {
|
|
313
319
|
const i = last ? this.lastIndexOf(search) : this.indexOf(search);
|
|
314
320
|
if (i === -1)
|
|
@@ -344,6 +350,9 @@ if (!globalThis.my_prototype_defined) {
|
|
|
344
350
|
.replace(new RegExp(cjk + '([~!;:,\\.\\?\u2026])([A-Za-z0-9])', 'g'), '$1$2 $3')
|
|
345
351
|
.replace(new RegExp(cjk + '([A-Za-z0-9`\\$%\\^&\\*\\-=\\+\\\\\\|\\/@\u00a1-\u00ff\u2022\u2027\u2150-\u218f])', 'g'), '$1 $2')
|
|
346
352
|
.replace(new RegExp('([A-Za-z0-9`\\$%\\^&\\*\\-=\\+\\\\\\|\\/@\u00a1-\u00ff\u2022\u2027\u2150-\u218f])' + cjk, 'g'), '$1 $2');
|
|
353
|
+
},
|
|
354
|
+
to_backslash() {
|
|
355
|
+
return this.replaceAll('/', '\\');
|
|
347
356
|
}
|
|
348
357
|
}),
|
|
349
358
|
// ------------ colors
|
|
@@ -404,11 +413,6 @@ if (!globalThis.my_prototype_defined) {
|
|
|
404
413
|
? ''
|
|
405
414
|
: fname.slice(index + 1);
|
|
406
415
|
}
|
|
407
|
-
}),
|
|
408
|
-
...to_method_property_descriptors({
|
|
409
|
-
to_backslash() {
|
|
410
|
-
return this.replaceAll('/', '\\');
|
|
411
|
-
}
|
|
412
416
|
})
|
|
413
417
|
});
|
|
414
418
|
// ------------------------------------ Date.prototype
|
package/utils.browser.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ export declare function delay(milliseconds: number, { signal }?: {
|
|
|
22
22
|
signal?: AbortSignal;
|
|
23
23
|
}): Promise<void>;
|
|
24
24
|
export declare class TimeoutError extends Error {
|
|
25
|
-
|
|
25
|
+
name: "TimeoutError";
|
|
26
26
|
}
|
|
27
27
|
/** 在指定的时间 (milliseconds) 内运行某个任务,超时之后
|
|
28
28
|
- 如果传入了 on_timeout 参数: 调用 on_timeout,返回 null
|
|
@@ -79,11 +79,13 @@ export declare function encode(str: string): Uint8Array<ArrayBufferLike>;
|
|
|
79
79
|
在流式处理 (buffer 可能不完整) 时,应使用独立的 TextDecoder 实例调用 decode(buffer, { stream: true }) */
|
|
80
80
|
export declare function decode(buffer: Uint8Array): string;
|
|
81
81
|
/** 字符串字典序比较 */
|
|
82
|
-
export declare function strcmp(l: string, r: string):
|
|
82
|
+
export declare function strcmp(l: string, r: string): 1 | 0 | -1;
|
|
83
83
|
/** 比较 1.10.02 这种版本号
|
|
84
84
|
- l, r: 两个版本号字符串
|
|
85
85
|
- loose?: 宽松模式,允许两个版本号格式(位数)不一致 */
|
|
86
86
|
export declare function vercmp(l: string, r: string, loose?: boolean): number;
|
|
87
|
+
/** 过滤符合 pattern 的行 */
|
|
88
|
+
export declare function grep(str: string, pattern: string | RegExp): string;
|
|
87
89
|
/** 模糊过滤字符串列表或对象列表,常用于根据用户输入补全或搜索过滤
|
|
88
90
|
- query: 查询字符串,要求为全小写
|
|
89
91
|
- list: 要过滤的列表
|
package/utils.browser.js
CHANGED
|
@@ -74,10 +74,7 @@ export async function delay(milliseconds, { signal } = {}) {
|
|
|
74
74
|
});
|
|
75
75
|
}
|
|
76
76
|
export class TimeoutError extends Error {
|
|
77
|
-
|
|
78
|
-
super(message, options);
|
|
79
|
-
this.name = this.constructor.name;
|
|
80
|
-
}
|
|
77
|
+
name = 'TimeoutError';
|
|
81
78
|
}
|
|
82
79
|
/** 在指定的时间 (milliseconds) 内运行某个任务,超时之后
|
|
83
80
|
- 如果传入了 on_timeout 参数: 调用 on_timeout,返回 null
|
|
@@ -262,6 +259,14 @@ export function vercmp(l, r, loose = false) {
|
|
|
262
259
|
// loose 下按短的优先,否则应该一样,为 0
|
|
263
260
|
return lparts.length - rparts.length;
|
|
264
261
|
}
|
|
262
|
+
/** 过滤符合 pattern 的行 */
|
|
263
|
+
export function grep(str, pattern) {
|
|
264
|
+
return str.split_lines()
|
|
265
|
+
.filter(typeof pattern === 'string'
|
|
266
|
+
? line => line.includes(pattern)
|
|
267
|
+
: line => pattern.test(line))
|
|
268
|
+
.join_lines();
|
|
269
|
+
}
|
|
265
270
|
/** 模糊过滤字符串列表或对象列表,常用于根据用户输入补全或搜索过滤
|
|
266
271
|
- query: 查询字符串,要求为全小写
|
|
267
272
|
- list: 要过滤的列表
|
package/utils.d.ts
CHANGED
|
@@ -40,11 +40,13 @@ export declare function filter_values<TObj extends Record<string, any>>(obj: TOb
|
|
|
40
40
|
/** 忽略对象中的 keys, 返回新对象 */
|
|
41
41
|
export declare function omit<TObj>(obj: TObj, omit_keys: string[]): TObj;
|
|
42
42
|
/** 字符串字典序比较 */
|
|
43
|
-
export declare function strcmp(l: string, r: string):
|
|
43
|
+
export declare function strcmp(l: string, r: string): 1 | 0 | -1;
|
|
44
44
|
/** 比较 1.10.02 这种版本号
|
|
45
45
|
- l, r: 两个版本号字符串
|
|
46
46
|
- loose?: 宽松模式,允许两个版本号格式(位数)不一致 */
|
|
47
47
|
export declare function vercmp(l: string, r: string, loose?: boolean): number;
|
|
48
|
+
/** 过滤符合 pattern 的行 */
|
|
49
|
+
export declare function grep(str: string, pattern: string | RegExp): string;
|
|
48
50
|
/** 模糊过滤字符串列表或对象列表,常用于根据用户输入补全或搜索过滤
|
|
49
51
|
- query: 查询字符串,要求为全小写
|
|
50
52
|
- list: 要过滤的列表
|
|
@@ -86,7 +88,7 @@ export declare class Timer {
|
|
|
86
88
|
export declare function log_line(): void;
|
|
87
89
|
export declare function delay(milliseconds: number, options?: TimerOptions): Promise<void>;
|
|
88
90
|
export declare class TimeoutError extends Error {
|
|
89
|
-
|
|
91
|
+
name: "TimeoutError";
|
|
90
92
|
}
|
|
91
93
|
/** 在指定的时间 (milliseconds) 内运行某个任务,超时之后
|
|
92
94
|
- 如果传入了 on_timeout 参数: 调用 on_timeout,返回 null
|
|
@@ -152,8 +154,11 @@ export declare function inspect(obj: any, options?: util.InspectOptions & {
|
|
|
152
154
|
limit?: number;
|
|
153
155
|
omit?: string[];
|
|
154
156
|
}): string;
|
|
157
|
+
/** 根据 enabled 选项返回有 / 无颜色的字符串 (str) */
|
|
158
|
+
export declare function colored(str: string, color: string, enabled?: boolean): any;
|
|
155
159
|
export declare namespace inspect {
|
|
156
160
|
const custom: typeof util.inspect.custom;
|
|
161
|
+
const defaultOptions: util.InspectOptions;
|
|
157
162
|
}
|
|
158
163
|
/** npm map-stream
|
|
159
164
|
filter will reemit the data if cb(err,pass) pass is truthy
|
package/utils.js
CHANGED
|
@@ -132,6 +132,14 @@ export function vercmp(l, r, loose = false) {
|
|
|
132
132
|
// loose 下按短的优先,否则应该一样,为 0
|
|
133
133
|
return lparts.length - rparts.length;
|
|
134
134
|
}
|
|
135
|
+
/** 过滤符合 pattern 的行 */
|
|
136
|
+
export function grep(str, pattern) {
|
|
137
|
+
return str.split_lines()
|
|
138
|
+
.filter(typeof pattern === 'string'
|
|
139
|
+
? line => line.includes(pattern)
|
|
140
|
+
: line => pattern.test(line))
|
|
141
|
+
.join_lines();
|
|
142
|
+
}
|
|
135
143
|
/** 模糊过滤字符串列表或对象列表,常用于根据用户输入补全或搜索过滤
|
|
136
144
|
- query: 查询字符串,要求为全小写
|
|
137
145
|
- list: 要过滤的列表
|
|
@@ -270,10 +278,7 @@ export async function delay(milliseconds, options) {
|
|
|
270
278
|
return timers.setTimeout(milliseconds, undefined, options);
|
|
271
279
|
}
|
|
272
280
|
export class TimeoutError extends Error {
|
|
273
|
-
|
|
274
|
-
super(message, options);
|
|
275
|
-
this.name = this.constructor.name;
|
|
276
|
-
}
|
|
281
|
+
name = 'TimeoutError';
|
|
277
282
|
}
|
|
278
283
|
/** 在指定的时间 (milliseconds) 内运行某个任务,超时之后
|
|
279
284
|
- 如果传入了 on_timeout 参数: 调用 on_timeout,返回 null
|
|
@@ -449,8 +454,13 @@ export function inspect(obj, options = {}) {
|
|
|
449
454
|
else
|
|
450
455
|
return text;
|
|
451
456
|
}
|
|
457
|
+
/** 根据 enabled 选项返回有 / 无颜色的字符串 (str) */
|
|
458
|
+
export function colored(str, color, enabled = inspect.defaultOptions.colors) {
|
|
459
|
+
return enabled ? str[color] : str;
|
|
460
|
+
}
|
|
452
461
|
(function (inspect) {
|
|
453
462
|
inspect.custom = util.inspect.custom;
|
|
463
|
+
inspect.defaultOptions = util.inspect.defaultOptions;
|
|
454
464
|
})(inspect || (inspect = {}));
|
|
455
465
|
// ------------------------------------ stream
|
|
456
466
|
/** npm map-stream
|