xshell 1.0.21 → 1.0.22

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/server.d.ts CHANGED
@@ -1,8 +1,6 @@
1
1
  /// <reference types="node" resolution-mode="require"/>
2
2
  /// <reference types="node" resolution-mode="require"/>
3
- /// <reference types="node" resolution-mode="require"/>
4
3
  import { type Server as HttpServer } from 'http';
5
- import { default as nodefs } from 'fs';
6
4
  import { WebSocketServer } from 'ws';
7
5
  import { default as Koa, type Context, type Next } from 'koa';
8
6
  import { type UserAgentContext } from 'koa-useragent';
@@ -20,7 +18,6 @@ declare module 'koa' {
20
18
  }
21
19
  }
22
20
  import { type Remote } from './net.js';
23
- import { type UFS } from './file.js';
24
21
  declare module 'http' {
25
22
  interface IncomingMessage {
26
23
  body?: Buffer;
@@ -51,15 +48,12 @@ export declare class Server {
51
48
  _router(ctx: Context, next: Next): Promise<void>;
52
49
  router(ctx: Context): Promise<boolean>;
53
50
  logger(ctx: Context): void;
54
- try_send(ctx: Context, fp: string, { fs, root, log_404, }: {
55
- fs?: (typeof nodefs) | UFS;
51
+ try_send(ctx: Context, fp: string, { root, log_404, }: {
56
52
  root: string;
57
53
  log_404?: boolean;
58
54
  }): Promise<boolean>;
59
55
  /** send file at `path` with the given `options` to the koa `ctx`. */
60
- fsend(ctx: Context, path: string, { fs, root, absolute }?: {
61
- /** `fs` */
62
- fs?: (typeof nodefs) | UFS;
56
+ fsend(ctx: Context, path: string, { root, absolute }?: {
63
57
  root?: string;
64
58
  /** `false` */
65
59
  absolute?: boolean;
package/server.js CHANGED
@@ -1,7 +1,6 @@
1
1
  import { createServer as http_create_server } from 'http';
2
2
  import zlib from 'zlib';
3
- import { default as nodefs } from 'fs';
4
- import { promisify } from 'util';
3
+ import { createReadStream } from 'fs';
5
4
  // --- 3rd party
6
5
  import upath from 'upath';
7
6
  import qs from 'qs';
@@ -12,7 +11,8 @@ import { default as Koa } from 'koa';
12
11
  import KoaCors from '@koa/cors';
13
12
  import KoaCompress from 'koa-compress';
14
13
  import { userAgent as KoaUserAgent } from 'koa-useragent';
15
- import { stream_to_buffer, inspect, output_width } from './utils.js';
14
+ import { stream_to_buffer, inspect, output_width, assert } from './utils.js';
15
+ import { fstat } from './file.js';
16
16
  // ------------ my server
17
17
  export class Server {
18
18
  app;
@@ -210,7 +210,7 @@ export class Server {
210
210
  // --- print log
211
211
  console.log(s);
212
212
  }
213
- async try_send(ctx, fp, { fs, root, log_404, }) {
213
+ async try_send(ctx, fp, { root, log_404, }) {
214
214
  const { request: { _path, path, method }, response, } = ctx;
215
215
  if (!(typeof response.body === 'undefined') || response.status !== 404)
216
216
  return true;
@@ -223,7 +223,7 @@ export class Server {
223
223
  console.log(s.red);
224
224
  }
225
225
  try {
226
- await this.fsend(ctx, fp, { fs, root });
226
+ await this.fsend(ctx, fp, { root });
227
227
  return true;
228
228
  }
229
229
  catch (error) {
@@ -235,8 +235,9 @@ export class Server {
235
235
  }
236
236
  }
237
237
  /** send file at `path` with the given `options` to the koa `ctx`. */
238
- async fsend(ctx, path, { fs = nodefs, root, absolute } = {}) {
239
- const { request, response, req } = ctx;
238
+ async fsend(ctx, path, { root, absolute } = {}) {
239
+ const { request } = ctx;
240
+ let { response } = ctx;
240
241
  if (!absolute && !root)
241
242
  throw new Error('fsend with `!absolute && !root`');
242
243
  if (absolute)
@@ -257,7 +258,7 @@ export class Server {
257
258
  // stat
258
259
  let stats;
259
260
  try {
260
- stats = await promisify(fs.stat)(path);
261
+ stats = await fstat(path);
261
262
  }
262
263
  catch (error) {
263
264
  if (['ENOENT', 'ENAMETOOLONG', 'ENOTDIR'].includes(error.code)) {
@@ -280,7 +281,7 @@ export class Server {
280
281
  if (!response.get('cache-control'))
281
282
  response.set('cache-control', 'max-age=0, must-revalidate');
282
283
  if (!response.get('last-modified'))
283
- response.set('last-modified', (stats.mtime || new Date()).toUTCString());
284
+ response.set('last-modified', stats.mtime.toUTCString());
284
285
  const fext = path.fext;
285
286
  if (!response.type)
286
287
  response.type = fext;
@@ -296,27 +297,28 @@ export class Server {
296
297
  const range_header = request.headers.range;
297
298
  const range_value = /=(.*)$/.exec(range_header)[1];
298
299
  const range = /^[\w]*?(\d*)-(\d*)$/.exec(range_value);
300
+ assert(stats.size <= Number.MAX_SAFE_INTEGER);
299
301
  let start = range[1] ? parseInt(range[1]) : undefined;
300
- let end = range[2] ? parseInt(range[2]) : stats.size - 1;
302
+ let end = range[2] ? parseInt(range[2]) : Number(stats.size) - 1;
301
303
  if (typeof start == 'undefined') {
302
- start = (stats.size - end);
303
- end = (stats.size - 1);
304
+ start = Number(stats.size) - end;
305
+ end = Number(stats.size) - 1;
304
306
  }
305
307
  const chunksize = (end - start + 1);
306
308
  response.status = 206;
307
309
  response.set('content-length', String(chunksize));
308
310
  response.set('content-range', `bytes ${start}-${end}/${stats.size}`);
309
- response.body = fs.createReadStream(path, { start, end });
311
+ response.body = createReadStream(path, { start, end });
310
312
  }
311
313
  catch (err) {
312
314
  response.status = 416;
313
315
  response.set('content-length', String(stats.size));
314
316
  response.set('content-range', `bytes */${stats.size}`);
315
- response.body = fs.createReadStream(path);
317
+ response.body = createReadStream(path);
316
318
  }
317
319
  else {
318
320
  response.set('content-length', String(stats.size));
319
- response.body = fs.createReadStream(path);
321
+ response.body = createReadStream(path);
320
322
  }
321
323
  return path;
322
324
  }
package/server.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["server.ts"],"names":[],"mappings":"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","sourcesContent":["import { createServer as http_create_server, type Server as HttpServer } from 'http'\nimport zlib from 'zlib'\nimport { default as nodefs, type Stats } from 'fs'\nimport { promisify } from 'util'\n\n// --- 3rd party\nimport upath from 'upath'\nimport qs from 'qs'\nimport resolve_safely from 'resolve-path'\nimport { WebSocketServer, type WebSocket } from 'ws'\n\n// --- koa & koa middleware\nimport { default as Koa, type Context, type Next } from 'koa'\n\nimport KoaCors from '@koa/cors'\nimport KoaCompress from 'koa-compress'\nimport { userAgent as KoaUserAgent, type UserAgentContext } from 'koa-useragent'\n\n\ndeclare module 'koa' {\n interface Request {\n /** 经过 decodeURIComponent 后,在路径重写之前的路径 */\n _path: string\n \n body: any\n }\n \n interface Context {\n compress: boolean\n userAgent: UserAgentContext['userAgent'] & { isWechat: boolean }\n }\n}\n\n// --- my libs\nimport { request as _request, type Remote } from './net.js'\nimport { stream_to_buffer, inspect, output_width } from './utils.js'\nimport { type UFS } from './file.js'\n\n\ndeclare module 'http' {\n interface IncomingMessage {\n body?: Buffer\n }\n \n interface ServerResponse {\n body?: Buffer\n }\n}\n\n\n// ------------ my server\nexport class Server {\n app: Koa\n \n handler: ReturnType<Koa['callback']>\n \n port: number\n \n server_http: HttpServer\n \n server_ws?: WebSocketServer\n \n remote?: Remote\n \n \n constructor (port: number, { remote }: { remote?: Remote } = { }) {\n this.port = port\n \n if (remote)\n this.remote = remote\n }\n \n \n /** start http server and listen */\n async start () {\n // --- init koa app\n let app = new Koa()\n \n app.on('error', (error, ctx) => {\n console.error(error)\n console.log(ctx)\n })\n \n app.use(this.entry.bind(this))\n \n app.use(KoaCompress({\n br: {\n chunkSize: 64 * 1024,\n \n // https://nodejs.org/api/zlib.html#zlib_class_brotlioptions\n params: {\n [zlib.constants.BROTLI_PARAM_MODE]: zlib.constants.BROTLI_MODE_TEXT,\n [zlib.constants.BROTLI_PARAM_QUALITY]: 3 // 默认为 11 (最大压缩),会导致 news/get 生成的 14 mb 的 json 压缩时长高达 24s\n },\n },\n threshold: 512\n }))\n \n app.use(KoaCors({ credentials: true }))\n app.use(KoaUserAgent)\n \n app.use(this._router.bind(this))\n \n this.app = app\n \n this.handler = this.app.callback()\n \n this.server_http = http_create_server(this.handler)\n \n \n // websocket rpc\n if (this.remote) {\n this.server_ws = new WebSocketServer({\n noServer: true,\n skipUTF8Validation: true,\n perMessageDeflate: true\n })\n \n this.server_ws.on('connection', (ws: WebSocket, request) => {\n ws.addEventListener('message', ({ data }) => {\n this.remote.handle(new Uint8Array(data as ArrayBuffer), ws)\n })\n })\n \n this.server_http.on('upgrade', (request, socket, head) => {\n // url 只有路径部分\n const {\n url, \n headers: { host = '', 'user-agent': ua },\n } = request\n \n const ip = (request.socket.remoteAddress as string).replace(/^::ffff:/, '')\n \n console.log(`${new Date().to_time_str()} ${(ip || '').pad(40)} ${(ua || '').limit(40)} ${'websocket'.pad(10).magenta} ${'connect'.pad(10).magenta}${host.pad(20)} ${url.pad(60).yellow}`)\n \n switch (url) {\n case '/':\n this.server_ws.handleUpgrade(request, socket, head, ws => {\n ws.binaryType = 'arraybuffer'\n this.server_ws.emit('connection', ws, request)\n })\n return\n \n default:\n console.log(`${' '.repeat(13)} connect 404: ${url}`.red)\n socket.destroy()\n }\n })\n }\n \n \n await new Promise<void>(resolve => {\n this.server_http.listen(this.port, resolve)\n })\n }\n \n \n stop () {\n this.server_http.close()\n }\n \n \n async entry (ctx: Context, next: Next) {\n let { response } = ctx\n \n await this.parse(ctx)\n \n // ------------ next\n try {\n await next()\n } catch (error) {\n if (error.status !== 404)\n console.error(error)\n response.status = error.status || 500\n response.body = inspect(error, { colors: false })\n response.type = 'text/plain'\n }\n }\n \n \n /** \n parse req.body to request.body \n process request.ip\n */\n async parse (ctx: Context) {\n let { req, request } = ctx\n \n const buf = await stream_to_buffer(req)\n if (buf.length)\n req.body = buf\n \n // --- parse request.ip\n request.ip = (request.headers['x-real-ip'] as string || request.ip).replace(/^::ffff:/, '')\n \n \n // --- parse body\n if (!req.body)\n return\n \n if (ctx.is('application/json') || ctx.is('text/plain'))\n request.body = JSON.parse(\n req.body.toString()\n )\n else if (ctx.is('application/x-www-form-urlencoded'))\n request.body = qs.parse(\n req.body.toString()\n )\n else if (ctx.is('multipart/form-data')) {\n throw new Error('multipart/form-data is not supported')\n } else\n request.body = req.body\n }\n \n \n async _router (ctx: Context, next: Next) {\n let { request } = ctx\n const _path = request._path = decodeURIComponent(request.path)\n Object.defineProperty(request, 'path', {\n value: _path,\n configurable: true,\n enumerable: true,\n writable: true\n })\n \n // ------------ log\n this.logger(ctx)\n \n // ------------ repl_router hook\n if (await global.repl_router?.(ctx))\n return\n \n if (await this.router(ctx))\n return\n \n await next?.()\n }\n \n \n async router (ctx: Context): Promise<boolean> {\n return false\n }\n \n \n logger (ctx: Context) {\n const { request } = ctx\n const {\n query, \n body, \n path, _path, \n protocol,\n host,\n req: { httpVersion: http_version },\n ip,\n } = request\n \n let { method } = request\n \n const ua = ctx.userAgent\n \n \n let s = ''\n \n // --- time\n s += `${new Date().to_time_str()} `\n \n \n // --- ip\n s += (ip || '').pad(40) + ' '\n \n \n // --- ua\n s += (() => {\n let t = ''\n if (ua.isMobile)\n t += 'mobile'\n if (ua.isDesktop)\n t += 'desktop'\n if (ua.isBot)\n t += `${ t ? ' ' : '' }${'robot'.blue}`\n if (ua.platform !== 'unknown' && !ua.os.startsWith('Windows'))\n t += '/' + ua.platform.toLowerCase().replace('apple mac', 'mac')\n if (ua.os !== 'unknown' && ua.platform !== 'Android')\n t += '/' + ua.os.toLowerCase()\n if (ua.browser !== 'unknown')\n t += '/' + ua.browser.toLowerCase()\n if (ua.isWechat)\n t += '/weixin'\n if (ua.version !== 'unknown')\n t += '/' + ua.version.split('.').slice(0, 2).join('.')\n return t\n })().pad(40) + ' '\n \n \n // --- https/2.0\n s += `${`${protocol.pad(5)}/${http_version}`.pad(10)} `\n \n \n // --- method\n method = method.toLowerCase()\n s += method === 'get' ? method.pad(10) : method.pad(10).yellow\n \n \n // --- host\n s += `${host.pad(20)} `\n \n \n // --- path\n s += (() => {\n if (path.toLowerCase() !== _path.toLowerCase())\n return `${_path.blue} → ${path}`\n if (!path.includes('.'))\n return path.yellow\n return path\n })()\n \n \n // --- query\n if (Object.keys(query).length) {\n let t = inspect(query, { compact: true })\n .replace('[Object: null prototype] ', '')\n \n if (t.endsWith('\\n'))\n t = t.slice(0, -1)\n \n s += (s + t).width > output_width ? '\\n' : ' '\n \n s += t\n }\n \n \n // --- body\n if (body && Object.keys(body).length)\n s += '\\n' + inspect(body).replace('[Object: null prototype] ', '')\n \n \n // --- print log\n console.log(s)\n }\n \n \n async try_send (\n ctx: Context, \n fp: string,\n {\n fs,\n root,\n log_404,\n }: {\n fs?: (typeof nodefs) | UFS\n root: string\n log_404?: boolean\n }) {\n const {\n request: { _path, path, method },\n response,\n } = ctx\n \n if (!(typeof response.body === 'undefined') || response.status !== 404)\n return true\n \n if (method !== 'HEAD' && method !== 'GET')\n return false\n \n function _log_404 () {\n let s = `${' '.repeat(13)} ${method.toLowerCase()} 404: ${path}`\n if (_path !== path)\n s += ` ${_path.bracket()}`\n console.log(s.red)\n }\n \n try {\n await this.fsend(ctx, fp, { fs, root })\n return true\n } catch (error) {\n if (error.status !== 404)\n throw error\n if (log_404)\n _log_404()\n return false\n }\n }\n \n \n /** send file at `path` with the given `options` to the koa `ctx`. */\n async fsend (\n ctx: Context,\n path: string,\n {\n fs = nodefs,\n root,\n absolute\n }: {\n /** `fs` */\n fs?: (typeof nodefs) | UFS\n \n root?: string\n \n /** `false` */\n absolute?: boolean\n \n } = { } as any\n ) {\n const { request, response, req } = ctx\n \n if (!absolute && !root)\n throw new Error('fsend with `!absolute && !root`')\n \n if (absolute)\n path = upath.resolve(path)\n else {\n if (path.startsWith(root))\n path = path.slice(root.length)\n \n if (path.startsWith('/'))\n path = path.slice(1)\n \n try {\n path = upath.normalize(\n resolve_safely(root, path)\n )\n } catch (error) {\n error.message += `, path: ${path}`\n throw error\n }\n }\n \n \n // stat\n let stats: Stats\n try {\n stats = await promisify(fs.stat)(path)\n } catch (error) {\n if (['ENOENT', 'ENAMETOOLONG', 'ENOTDIR'].includes(error.code)) {\n error.status = 404\n throw error\n }\n \n error.status = 500\n error.message = `fs.stat 出错: ${error.message}`\n throw error\n }\n \n \n // size limit\n // if (stats.size >= 100 * 2**20) {\n // let error = new Error('body.length >= 100 mb')\n // ;(error as any).status = 500\n // throw error\n // }\n \n \n // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Ranges\n // advertise server support of partial requests\n response.set('accept-ranges', 'bytes')\n \n if (!response.get('cache-control'))\n response.set('cache-control', 'max-age=0, must-revalidate')\n \n if (!response.get('last-modified'))\n response.set('last-modified', (stats.mtime || new Date()).toUTCString())\n \n const fext = path.fext\n \n if (!response.type)\n response.type = fext\n \n if (fext === '.pdf')\n response.set('content-disposition', `attachment; filename=\"${encodeURIComponent(path.fname)}\"`)\n \n if (request.fresh) {\n response.status = 304\n // 以上会自动设置 response.body = null\n return path\n }\n \n if (request.headers.range)\n try {\n const range_header = request.headers.range\n const range_value = /=(.*)$/.exec(range_header)[1]\n const range = /^[\\w]*?(\\d*)-(\\d*)$/.exec(range_value)\n \n let start = range[1] ? parseInt(range[1]) : undefined\n let end = range[2] ? parseInt(range[2]) : stats.size - 1\n \n if (typeof start == 'undefined') {\n start = (stats.size - end)\n end = (stats.size - 1)\n }\n \n const chunksize = (end - start + 1)\n \n response.status = 206\n response.set('content-length', String(chunksize))\n response.set('content-range', `bytes ${start}-${end}/${stats.size}`)\n response.body = fs.createReadStream(path, { start, end })\n } catch (err) {\n response.status = 416\n response.set('content-length', String(stats.size))\n response.set('content-range', `bytes */${stats.size}`)\n response.body = fs.createReadStream(path)\n }\n else {\n response.set('content-length', String(stats.size))\n response.body = fs.createReadStream(path)\n }\n \n return path\n }\n}\n\n"]}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["server.ts"],"names":[],"mappings":"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","sourcesContent":["import { createServer as http_create_server, type Server as HttpServer } from 'http'\nimport zlib from 'zlib'\nimport { createReadStream } from 'fs'\n\n// --- 3rd party\nimport upath from 'upath'\nimport qs from 'qs'\nimport resolve_safely from 'resolve-path'\nimport { WebSocketServer, type WebSocket } from 'ws'\n\n// --- koa & koa middleware\nimport { default as Koa, type Context, type Next } from 'koa'\n\nimport KoaCors from '@koa/cors'\nimport KoaCompress from 'koa-compress'\nimport { userAgent as KoaUserAgent, type UserAgentContext } from 'koa-useragent'\n\n\ndeclare module 'koa' {\n interface Request {\n /** 经过 decodeURIComponent 后,在路径重写之前的路径 */\n _path: string\n \n body: any\n }\n \n interface Context {\n compress: boolean\n userAgent: UserAgentContext['userAgent'] & { isWechat: boolean }\n }\n}\n\n// --- my libs\nimport { request as _request, type Remote } from './net.js'\nimport { stream_to_buffer, inspect, output_width, assert } from './utils.js'\nimport { fstat, type FStats } from './file.js'\n\n\ndeclare module 'http' {\n interface IncomingMessage {\n body?: Buffer\n }\n \n interface ServerResponse {\n body?: Buffer\n }\n}\n\n\n// ------------ my server\nexport class Server {\n app: Koa\n \n handler: ReturnType<Koa['callback']>\n \n port: number\n \n server_http: HttpServer\n \n server_ws?: WebSocketServer\n \n remote?: Remote\n \n \n constructor (port: number, { remote }: { remote?: Remote } = { }) {\n this.port = port\n \n if (remote)\n this.remote = remote\n }\n \n \n /** start http server and listen */\n async start () {\n // --- init koa app\n let app = new Koa()\n \n app.on('error', (error, ctx) => {\n console.error(error)\n console.log(ctx)\n })\n \n app.use(this.entry.bind(this))\n \n app.use(KoaCompress({\n br: {\n chunkSize: 64 * 1024,\n \n // https://nodejs.org/api/zlib.html#zlib_class_brotlioptions\n params: {\n [zlib.constants.BROTLI_PARAM_MODE]: zlib.constants.BROTLI_MODE_TEXT,\n [zlib.constants.BROTLI_PARAM_QUALITY]: 3 // 默认为 11 (最大压缩),会导致 news/get 生成的 14 mb 的 json 压缩时长高达 24s\n },\n },\n threshold: 512\n }))\n \n app.use(KoaCors({ credentials: true }))\n app.use(KoaUserAgent)\n \n app.use(this._router.bind(this))\n \n this.app = app\n \n this.handler = this.app.callback()\n \n this.server_http = http_create_server(this.handler)\n \n \n // websocket rpc\n if (this.remote) {\n this.server_ws = new WebSocketServer({\n noServer: true,\n skipUTF8Validation: true,\n perMessageDeflate: true\n })\n \n this.server_ws.on('connection', (ws: WebSocket, request) => {\n ws.addEventListener('message', ({ data }) => {\n this.remote.handle(new Uint8Array(data as ArrayBuffer), ws)\n })\n })\n \n this.server_http.on('upgrade', (request, socket, head) => {\n // url 只有路径部分\n const {\n url, \n headers: { host = '', 'user-agent': ua },\n } = request\n \n const ip = (request.socket.remoteAddress as string).replace(/^::ffff:/, '')\n \n console.log(`${new Date().to_time_str()} ${(ip || '').pad(40)} ${(ua || '').limit(40)} ${'websocket'.pad(10).magenta} ${'connect'.pad(10).magenta}${host.pad(20)} ${url.pad(60).yellow}`)\n \n switch (url) {\n case '/':\n this.server_ws.handleUpgrade(request, socket, head, ws => {\n ws.binaryType = 'arraybuffer'\n this.server_ws.emit('connection', ws, request)\n })\n return\n \n default:\n console.log(`${' '.repeat(13)} connect 404: ${url}`.red)\n socket.destroy()\n }\n })\n }\n \n \n await new Promise<void>(resolve => {\n this.server_http.listen(this.port, resolve)\n })\n }\n \n \n stop () {\n this.server_http.close()\n }\n \n \n async entry (ctx: Context, next: Next) {\n let { response } = ctx\n \n await this.parse(ctx)\n \n // ------------ next\n try {\n await next()\n } catch (error) {\n if (error.status !== 404)\n console.error(error)\n response.status = error.status || 500\n response.body = inspect(error, { colors: false })\n response.type = 'text/plain'\n }\n }\n \n \n /** \n parse req.body to request.body \n process request.ip\n */\n async parse (ctx: Context) {\n let { req, request } = ctx\n \n const buf = await stream_to_buffer(req)\n if (buf.length)\n req.body = buf\n \n // --- parse request.ip\n request.ip = (request.headers['x-real-ip'] as string || request.ip).replace(/^::ffff:/, '')\n \n \n // --- parse body\n if (!req.body)\n return\n \n if (ctx.is('application/json') || ctx.is('text/plain'))\n request.body = JSON.parse(\n req.body.toString()\n )\n else if (ctx.is('application/x-www-form-urlencoded'))\n request.body = qs.parse(\n req.body.toString()\n )\n else if (ctx.is('multipart/form-data')) {\n throw new Error('multipart/form-data is not supported')\n } else\n request.body = req.body\n }\n \n \n async _router (ctx: Context, next: Next) {\n let { request } = ctx\n const _path = request._path = decodeURIComponent(request.path)\n Object.defineProperty(request, 'path', {\n value: _path,\n configurable: true,\n enumerable: true,\n writable: true\n })\n \n // ------------ log\n this.logger(ctx)\n \n // ------------ repl_router hook\n if (await global.repl_router?.(ctx))\n return\n \n if (await this.router(ctx))\n return\n \n await next?.()\n }\n \n \n async router (ctx: Context): Promise<boolean> {\n return false\n }\n \n \n logger (ctx: Context) {\n const { request } = ctx\n const {\n query, \n body, \n path, _path, \n protocol,\n host,\n req: { httpVersion: http_version },\n ip,\n } = request\n \n let { method } = request\n \n const ua = ctx.userAgent\n \n \n let s = ''\n \n // --- time\n s += `${new Date().to_time_str()} `\n \n \n // --- ip\n s += (ip || '').pad(40) + ' '\n \n \n // --- ua\n s += (() => {\n let t = ''\n if (ua.isMobile)\n t += 'mobile'\n if (ua.isDesktop)\n t += 'desktop'\n if (ua.isBot)\n t += `${ t ? ' ' : '' }${'robot'.blue}`\n if (ua.platform !== 'unknown' && !ua.os.startsWith('Windows'))\n t += '/' + ua.platform.toLowerCase().replace('apple mac', 'mac')\n if (ua.os !== 'unknown' && ua.platform !== 'Android')\n t += '/' + ua.os.toLowerCase()\n if (ua.browser !== 'unknown')\n t += '/' + ua.browser.toLowerCase()\n if (ua.isWechat)\n t += '/weixin'\n if (ua.version !== 'unknown')\n t += '/' + ua.version.split('.').slice(0, 2).join('.')\n return t\n })().pad(40) + ' '\n \n \n // --- https/2.0\n s += `${`${protocol.pad(5)}/${http_version}`.pad(10)} `\n \n \n // --- method\n method = method.toLowerCase()\n s += method === 'get' ? method.pad(10) : method.pad(10).yellow\n \n \n // --- host\n s += `${host.pad(20)} `\n \n \n // --- path\n s += (() => {\n if (path.toLowerCase() !== _path.toLowerCase())\n return `${_path.blue} → ${path}`\n if (!path.includes('.'))\n return path.yellow\n return path\n })()\n \n \n // --- query\n if (Object.keys(query).length) {\n let t = inspect(query, { compact: true })\n .replace('[Object: null prototype] ', '')\n \n if (t.endsWith('\\n'))\n t = t.slice(0, -1)\n \n s += (s + t).width > output_width ? '\\n' : ' '\n \n s += t\n }\n \n \n // --- body\n if (body && Object.keys(body).length)\n s += '\\n' + inspect(body).replace('[Object: null prototype] ', '')\n \n \n // --- print log\n console.log(s)\n }\n \n \n async try_send (\n ctx: Context, \n fp: string,\n {\n root,\n log_404,\n }: {\n root: string\n log_404?: boolean\n }) {\n const {\n request: { _path, path, method },\n response,\n } = ctx\n \n if (!(typeof response.body === 'undefined') || response.status !== 404)\n return true\n \n if (method !== 'HEAD' && method !== 'GET')\n return false\n \n function _log_404 () {\n let s = `${' '.repeat(13)} ${method.toLowerCase()} 404: ${path}`\n if (_path !== path)\n s += ` ${_path.bracket()}`\n console.log(s.red)\n }\n \n try {\n await this.fsend(ctx, fp, { root })\n return true\n } catch (error) {\n if (error.status !== 404)\n throw error\n if (log_404)\n _log_404()\n return false\n }\n }\n \n \n /** send file at `path` with the given `options` to the koa `ctx`. */\n async fsend (\n ctx: Context,\n path: string,\n {\n root,\n absolute\n }: {\n root?: string\n \n /** `false` */\n absolute?: boolean\n \n } = { } as any\n ) {\n const { request } = ctx\n let { response } = ctx\n \n if (!absolute && !root)\n throw new Error('fsend with `!absolute && !root`')\n \n if (absolute)\n path = upath.resolve(path)\n else {\n if (path.startsWith(root))\n path = path.slice(root.length)\n \n if (path.startsWith('/'))\n path = path.slice(1)\n \n try {\n path = upath.normalize(\n resolve_safely(root, path)\n )\n } catch (error) {\n error.message += `, path: ${path}`\n throw error\n }\n }\n \n \n // stat\n let stats: FStats\n try {\n stats = await fstat(path)\n } catch (error) {\n if (['ENOENT', 'ENAMETOOLONG', 'ENOTDIR'].includes(error.code)) {\n error.status = 404\n throw error\n }\n \n error.status = 500\n error.message = `fs.stat 出错: ${error.message}`\n throw error\n }\n \n \n // size limit\n // if (stats.size >= 100 * 2**20) {\n // let error = new Error('body.length >= 100 mb')\n // ;(error as any).status = 500\n // throw error\n // }\n \n \n // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Ranges\n // advertise server support of partial requests\n response.set('accept-ranges', 'bytes')\n \n if (!response.get('cache-control'))\n response.set('cache-control', 'max-age=0, must-revalidate')\n \n if (!response.get('last-modified'))\n response.set('last-modified', stats.mtime.toUTCString())\n \n const fext = path.fext\n \n if (!response.type)\n response.type = fext\n \n if (fext === '.pdf')\n response.set('content-disposition', `attachment; filename=\"${encodeURIComponent(path.fname)}\"`)\n \n if (request.fresh) {\n response.status = 304\n // 以上会自动设置 response.body = null\n return path\n }\n \n if (request.headers.range)\n try {\n const range_header = request.headers.range\n const range_value = /=(.*)$/.exec(range_header)[1]\n const range = /^[\\w]*?(\\d*)-(\\d*)$/.exec(range_value)\n \n assert(stats.size <= Number.MAX_SAFE_INTEGER)\n \n let start = range[1] ? parseInt(range[1]) : undefined\n let end = range[2] ? parseInt(range[2]) : Number(stats.size) - 1\n \n if (typeof start == 'undefined') {\n start = Number(stats.size) - end\n end = Number(stats.size) - 1\n }\n \n const chunksize = (end - start + 1)\n \n response.status = 206\n response.set('content-length', String(chunksize))\n response.set('content-range', `bytes ${start}-${end}/${stats.size}`)\n response.body = createReadStream(path, { start, end })\n } catch (err) {\n response.status = 416\n response.set('content-length', String(stats.size))\n response.set('content-range', `bytes */${stats.size}`)\n response.body = createReadStream(path)\n }\n else {\n response.set('content-length', String(stats.size))\n response.body = createReadStream(path)\n }\n \n return path\n }\n}\n\n"]}
package/tsconfig.json CHANGED
@@ -18,7 +18,7 @@
18
18
  "importHelpers": true,
19
19
  // "watch": false
20
20
  "incremental": true,
21
- "tsBuildInfoFile": "./node_modules/.tsbuildinfo.json",
21
+ "tsBuildInfoFile": "t:/1/xsh/.tsbuildinfo",
22
22
 
23
23
 
24
24
  // --- emit
@@ -56,7 +56,10 @@ export declare function genid(): number;
56
56
  export declare class Timer {
57
57
  started: number;
58
58
  ended: number;
59
+ /** 停止秒表,保存读数 */
59
60
  stop(): void;
61
+ /** 如果秒表未停止,获取当前秒表读数;
62
+ 如果秒表已停止,获取停止时的秒表读数; */
60
63
  get(): number;
61
64
  getstr(): string;
62
65
  print(): void;
package/utils.browser.js CHANGED
@@ -154,13 +154,14 @@ export function genid() {
154
154
  export class Timer {
155
155
  started = new Date().getTime();
156
156
  ended;
157
+ /** 停止秒表,保存读数 */
157
158
  stop() {
158
159
  this.ended = new Date().getTime();
159
160
  }
161
+ /** 如果秒表未停止,获取当前秒表读数;
162
+ 如果秒表已停止,获取停止时的秒表读数; */
160
163
  get() {
161
- if (!this.ended)
162
- this.stop();
163
- return this.ended - this.started;
164
+ return (this.ended || new Date().getTime()) - this.started;
164
165
  }
165
166
  getstr() {
166
167
  return `(${delta2str(this.get())})`;
@@ -1 +1 @@
1
- {"version":3,"file":"utils.browser.js","sourceRoot":"","sources":["utils.browser.ts"],"names":[],"mappings":"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","sourcesContent":["import { t } from './i18n/instance.js'\n\n\nexport const noop = () => { }\n\n\nexport function assert (assertion: any, message?: string): never | void {\n if (assertion)\n return\n \n debugger\n \n throw Object.assign(\n new Error(`${t('断言失败')}: ${ message ? `${message}: ` : '' }${assertion}`),\n { assertion }\n )\n}\n\n\nexport async function delay (milliseconds: number) {\n return new Promise<void>(resolve => {\n setTimeout(resolve, milliseconds)\n })\n}\n\n\nexport async function timeout (milliseconds: number) {\n const error = new Error(t('超时错误'))\n await delay(milliseconds)\n throw error\n}\n\n\n/** https://stackoverflow.com/questions/63297164/how-to-only-accept-arraybuffer-as-parameter */\nexport type StrictArrayBuffer = ArrayBuffer & { buffer?: undefined }\n\n\nexport interface Deferred <TValue> extends Promise<TValue> {\n resolve (value: TValue | PromiseLike<TValue>): void\n reject (reason?: Error): void\n}\n\n/** 创建一个 promise,后续可调用 promise.resolve, promise.reject 方法设置其状态和值 \n - initial?: `undefined` 传入非 undefined 值(包括 null)时直接设置为 resolved 状态 */\nexport function defer <TValue> (initial?: TValue): Deferred<TValue> {\n if (initial === undefined) {\n let resolve: (value: TValue | PromiseLike<TValue>) => void\n let reject: (reason?: Error) => void\n \n let promise = new Promise<TValue>((_resolve, _reject) => {\n resolve = _resolve\n reject = _reject\n })\n \n return Object.assign(promise, { resolve, reject })\n } else\n return Object.assign(Promise.resolve(initial), {\n resolve () { },\n reject () { }\n })\n}\n\n\nexport interface LockedAction <TResource, TResult> {\n (resource: TResource): Promise<TResult>\n}\n\n\n/** @example\n let lock = new Lock(redis)\n \n // 锁定资源后在 action 回调中操作资源,回调 promise 完成后自动释放资源,\n // 三秒内未成功独占资源直接抛出 TimeoutError (开始执行后不受 signal abort 影响)\n await lock.request(async redis => {\n const value = await redis.get('key')\n await redis.set('key', value * 2)\n }, AbortSignal.timeout(3000)) \n \n 参考:\n https://developer.mozilla.org/en-US/docs/Web/API/Web_Locks_API \n https://github.com/metarhia/web-locks \n https://www.npmjs.com/package/async-lock */\nexport class Lock <TResource = void> {\n /** 如果操作不需要独占资源,可以直接通过 lock.resource 访问,否则需要通过 await lock.request() 独占资源后再访问 */\n resource: TResource\n \n /** 等待链,新的 await lock.request() 调用会等待当前等待链尾部的 promise 完成,并作为新的尾部 */\n ptail = defer<void>(null)\n \n /** 查询当前资源是否属于被锁定的状态,方便在资源闲置时做一些可选操作(操作前仍需锁定),或者做一些状态展示 */\n locked = false\n \n \n /** 可以不传 resource,表示管理某个抽象或虚拟的资源 */\n constructor (resource?: TResource) {\n this.resource = resource\n }\n \n \n /** 通过 await lock.request() 锁定资源以便独占访问\n 成功返回之后由调用方负责调用 release 方法释放资源\n 在 signal aborted 时抛出错误结束等待,且由内部实现自动释放资源 */\n // async request (action: (resource: TResource) => Promise<void>, signal?: AbortSignal): Promise<void>\n // async request <TResult> (action: <TResult> (resource: TResource) => Promise<TResult>, signal?: AbortSignal): Promise<TResult>\n async request <TResult> (action: LockedAction<TResource, TResult>, signal?: AbortSignal): Promise<TResult> {\n signal?.throwIfAborted()\n \n const ptail = this.ptail\n \n let pcurrent = this.ptail = defer<void>()\n \n this.locked = true\n \n return new Promise<TResult>((resolve, reject) => {\n // 下面两种情况,先发生的决定 request 返回的 promise 状态\n // 不管是否 aborted, 都要等资源被前一次调用释放,先 aborted 只是将控制权交回给调用者,在锁定资源后不执行 action, 直接释放\n \n /** 防止执行过程中 signal abort */\n let executing = false\n \n signal?.addEventListener('abort', () => {\n if (!executing)\n // 这里不能释放锁,需要等 ptail resolve 后拿到资源再释放\n reject(signal.reason)\n }, { once: true })\n \n ptail.then(async () => {\n // 这里已经能保证独占访问资源\n \n // 如果 aborted, 可以理解为独占资源失败,调用者不会使用资源,直接释放\n if (signal?.aborted)\n reject(signal.reason)\n else\n // 由调用者去操作资源\n try {\n executing = true\n resolve(await action(this.resource))\n } catch (error) {\n reject(error)\n }\n \n \n // 下面开始释放锁\n \n // assert(this.locked)\n if (!this.locked)\n reject(new Error(t('尝试释放未锁定的锁,这不应该发生')))\n \n this.locked = false\n \n pcurrent.resolve()\n }\n )})\n }\n}\n\n\nexport async function debug (milliseconds: number = 3000) {\n await delay(milliseconds)\n debugger\n}\n\nglobalThis.debug = debug\n\n\n/** 字符串字典序比较 */\nexport function strcmp (l: string, r: string) {\n if (l === r) return 0\n if (l < r) return -1\n return 1\n}\n\n\n/** 拼接 TypedArrays 生成一个完整的 Uint8Array */\nexport function concat (arrays: ArrayBufferView[]) {\n let length = 0\n for (const a of arrays)\n length += a.byteLength\n \n let buf = new Uint8Array(length)\n let offset = 0\n for (const a of arrays) {\n const uint8view = new Uint8Array(a.buffer, a.byteOffset, a.byteLength)\n buf.set(uint8view, offset)\n offset += uint8view.byteLength\n }\n \n return buf\n}\n\n\n/** 时间间隔 (milliseconds) 格式化 */\nexport function delta2str (delta: number) {\n if (delta < 1)\n return '0 ms'\n \n // [1, 1000) ms\n if (delta < 1000)\n return `${delta} ms`\n \n // 1.123 s\n if (1000 <= delta && delta < 1000 * 60)\n return `${(delta / 1000).toFixed(1)} s`\n \n // 1 min 12 s [1 min 0s, 60 min)\n const seconds = Math.trunc(delta / 1000)\n \n if (seconds < 60 * 60)\n return `${Math.trunc(seconds / 60)} min ${seconds % 60} s`\n \n const hour = Math.trunc(seconds / 3600)\n \n return `${hour} h ${Math.trunc((seconds - 3600 * hour) / 60)} min ${seconds % 60} s`\n}\n\n\n/** generate random id */\nexport function genid () {\n return Math.random() * 2**53\n}\n\n\nexport class Timer {\n started = new Date().getTime()\n \n ended: number\n \n stop () {\n this.ended = new Date().getTime()\n }\n \n get () {\n if (!this.ended)\n this.stop()\n \n return this.ended - this.started\n }\n \n getstr () {\n return `(${delta2str(this.get())})`\n }\n \n print () {\n console.log(this.getstr())\n }\n}\n\n"]}
1
+ {"version":3,"file":"utils.browser.js","sourceRoot":"","sources":["utils.browser.ts"],"names":[],"mappings":"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","sourcesContent":["import { t } from './i18n/instance.js'\n\n\nexport const noop = () => { }\n\n\nexport function assert (assertion: any, message?: string): never | void {\n if (assertion)\n return\n \n debugger\n \n throw Object.assign(\n new Error(`${t('断言失败')}: ${ message ? `${message}: ` : '' }${assertion}`),\n { assertion }\n )\n}\n\n\nexport async function delay (milliseconds: number) {\n return new Promise<void>(resolve => {\n setTimeout(resolve, milliseconds)\n })\n}\n\n\nexport async function timeout (milliseconds: number) {\n const error = new Error(t('超时错误'))\n await delay(milliseconds)\n throw error\n}\n\n\n/** https://stackoverflow.com/questions/63297164/how-to-only-accept-arraybuffer-as-parameter */\nexport type StrictArrayBuffer = ArrayBuffer & { buffer?: undefined }\n\n\nexport interface Deferred <TValue> extends Promise<TValue> {\n resolve (value: TValue | PromiseLike<TValue>): void\n reject (reason?: Error): void\n}\n\n/** 创建一个 promise,后续可调用 promise.resolve, promise.reject 方法设置其状态和值 \n - initial?: `undefined` 传入非 undefined 值(包括 null)时直接设置为 resolved 状态 */\nexport function defer <TValue> (initial?: TValue): Deferred<TValue> {\n if (initial === undefined) {\n let resolve: (value: TValue | PromiseLike<TValue>) => void\n let reject: (reason?: Error) => void\n \n let promise = new Promise<TValue>((_resolve, _reject) => {\n resolve = _resolve\n reject = _reject\n })\n \n return Object.assign(promise, { resolve, reject })\n } else\n return Object.assign(Promise.resolve(initial), {\n resolve () { },\n reject () { }\n })\n}\n\n\nexport interface LockedAction <TResource, TResult> {\n (resource: TResource): Promise<TResult>\n}\n\n\n/** @example\n let lock = new Lock(redis)\n \n // 锁定资源后在 action 回调中操作资源,回调 promise 完成后自动释放资源,\n // 三秒内未成功独占资源直接抛出 TimeoutError (开始执行后不受 signal abort 影响)\n await lock.request(async redis => {\n const value = await redis.get('key')\n await redis.set('key', value * 2)\n }, AbortSignal.timeout(3000)) \n \n 参考:\n https://developer.mozilla.org/en-US/docs/Web/API/Web_Locks_API \n https://github.com/metarhia/web-locks \n https://www.npmjs.com/package/async-lock */\nexport class Lock <TResource = void> {\n /** 如果操作不需要独占资源,可以直接通过 lock.resource 访问,否则需要通过 await lock.request() 独占资源后再访问 */\n resource: TResource\n \n /** 等待链,新的 await lock.request() 调用会等待当前等待链尾部的 promise 完成,并作为新的尾部 */\n ptail = defer<void>(null)\n \n /** 查询当前资源是否属于被锁定的状态,方便在资源闲置时做一些可选操作(操作前仍需锁定),或者做一些状态展示 */\n locked = false\n \n \n /** 可以不传 resource,表示管理某个抽象或虚拟的资源 */\n constructor (resource?: TResource) {\n this.resource = resource\n }\n \n \n /** 通过 await lock.request() 锁定资源以便独占访问\n 成功返回之后由调用方负责调用 release 方法释放资源\n 在 signal aborted 时抛出错误结束等待,且由内部实现自动释放资源 */\n // async request (action: (resource: TResource) => Promise<void>, signal?: AbortSignal): Promise<void>\n // async request <TResult> (action: <TResult> (resource: TResource) => Promise<TResult>, signal?: AbortSignal): Promise<TResult>\n async request <TResult> (action: LockedAction<TResource, TResult>, signal?: AbortSignal): Promise<TResult> {\n signal?.throwIfAborted()\n \n const ptail = this.ptail\n \n let pcurrent = this.ptail = defer<void>()\n \n this.locked = true\n \n return new Promise<TResult>((resolve, reject) => {\n // 下面两种情况,先发生的决定 request 返回的 promise 状态\n // 不管是否 aborted, 都要等资源被前一次调用释放,先 aborted 只是将控制权交回给调用者,在锁定资源后不执行 action, 直接释放\n \n /** 防止执行过程中 signal abort */\n let executing = false\n \n signal?.addEventListener('abort', () => {\n if (!executing)\n // 这里不能释放锁,需要等 ptail resolve 后拿到资源再释放\n reject(signal.reason)\n }, { once: true })\n \n ptail.then(async () => {\n // 这里已经能保证独占访问资源\n \n // 如果 aborted, 可以理解为独占资源失败,调用者不会使用资源,直接释放\n if (signal?.aborted)\n reject(signal.reason)\n else\n // 由调用者去操作资源\n try {\n executing = true\n resolve(await action(this.resource))\n } catch (error) {\n reject(error)\n }\n \n \n // 下面开始释放锁\n \n // assert(this.locked)\n if (!this.locked)\n reject(new Error(t('尝试释放未锁定的锁,这不应该发生')))\n \n this.locked = false\n \n pcurrent.resolve()\n }\n )})\n }\n}\n\n\nexport async function debug (milliseconds: number = 3000) {\n await delay(milliseconds)\n debugger\n}\n\nglobalThis.debug = debug\n\n\n/** 字符串字典序比较 */\nexport function strcmp (l: string, r: string) {\n if (l === r) return 0\n if (l < r) return -1\n return 1\n}\n\n\n/** 拼接 TypedArrays 生成一个完整的 Uint8Array */\nexport function concat (arrays: ArrayBufferView[]) {\n let length = 0\n for (const a of arrays)\n length += a.byteLength\n \n let buf = new Uint8Array(length)\n let offset = 0\n for (const a of arrays) {\n const uint8view = new Uint8Array(a.buffer, a.byteOffset, a.byteLength)\n buf.set(uint8view, offset)\n offset += uint8view.byteLength\n }\n \n return buf\n}\n\n\n/** 时间间隔 (milliseconds) 格式化 */\nexport function delta2str (delta: number) {\n if (delta < 1)\n return '0 ms'\n \n // [1, 1000) ms\n if (delta < 1000)\n return `${delta} ms`\n \n // 1.123 s\n if (1000 <= delta && delta < 1000 * 60)\n return `${(delta / 1000).toFixed(1)} s`\n \n // 1 min 12 s [1 min 0s, 60 min)\n const seconds = Math.trunc(delta / 1000)\n \n if (seconds < 60 * 60)\n return `${Math.trunc(seconds / 60)} min ${seconds % 60} s`\n \n const hour = Math.trunc(seconds / 3600)\n \n return `${hour} h ${Math.trunc((seconds - 3600 * hour) / 60)} min ${seconds % 60} s`\n}\n\n\n/** generate random id */\nexport function genid () {\n return Math.random() * 2**53\n}\n\n\nexport class Timer {\n started = new Date().getTime()\n \n ended: number\n \n /** 停止秒表,保存读数 */\n stop () {\n this.ended = new Date().getTime()\n }\n \n /** 如果秒表未停止,获取当前秒表读数;\n 如果秒表已停止,获取停止时的秒表读数; */\n get () {\n return (this.ended || new Date().getTime()) - this.started\n }\n \n getstr () {\n return `(${delta2str(this.get())})`\n }\n \n print () {\n console.log(this.getstr())\n }\n}\n\n"]}
package/utils.d.ts CHANGED
@@ -29,16 +29,16 @@ export declare function genid(): number;
29
29
  export declare class Timer {
30
30
  started: number;
31
31
  ended: number;
32
+ /** 停止秒表,保存读数 */
32
33
  stop(): void;
34
+ /** 如果秒表未停止,获取当前秒表读数;
35
+ 如果秒表已停止,获取停止时的秒表读数; */
33
36
  get(): number;
34
- getstr(): string;
37
+ /** 获取时间表示字符串,如 1.2 s
38
+ - bracket?: `true` 字符串前后加上括号,如 (1.2 s) */
39
+ getstr(bracket?: boolean): string;
35
40
  print(): void;
36
41
  }
37
- export declare function log_section(message: string, { time, timestamp, color, }?: {
38
- time?: boolean;
39
- timestamp?: boolean | Date;
40
- color?: 'green' | 'red' | 'yellow';
41
- }): void;
42
42
  export declare function log_line(): void;
43
43
  export declare function delay(milliseconds: number): Promise<void>;
44
44
  export declare function timeout(milliseconds: number): Promise<void>;
package/utils.js CHANGED
@@ -120,37 +120,28 @@ export function genid() {
120
120
  export class Timer {
121
121
  started = new Date().getTime();
122
122
  ended;
123
+ /** 停止秒表,保存读数 */
123
124
  stop() {
124
125
  this.ended = new Date().getTime();
125
126
  }
127
+ /** 如果秒表未停止,获取当前秒表读数;
128
+ 如果秒表已停止,获取停止时的秒表读数; */
126
129
  get() {
127
- if (!this.ended)
128
- this.stop();
129
- return this.ended - this.started;
130
+ return (this.ended || new Date().getTime()) - this.started;
130
131
  }
131
- getstr() {
132
- return `(${delta2str(this.get())})`;
132
+ /** 获取时间表示字符串,如 1.2 s
133
+ - bracket?: `true` 字符串前后加上括号,如 (1.2 s) */
134
+ getstr(bracket = false) {
135
+ let s = delta2str(this.get());
136
+ if (bracket)
137
+ return s.bracket();
138
+ else
139
+ return s;
133
140
  }
134
141
  print() {
135
- console.log(this.getstr());
142
+ console.log(this.getstr(true));
136
143
  }
137
144
  }
138
- export function log_section(message, { time = false, timestamp = false, color = undefined, } = {}) {
139
- const stime = (() => {
140
- if (time)
141
- return delta2str(new Date().getTime() - global.started_at.getTime()).pad(4, { position: 'left' });
142
- if (timestamp)
143
- if (typeof timestamp === 'object')
144
- return `${timestamp.to_str()}`;
145
- else
146
- return `${new Date().to_str()}`;
147
- return '';
148
- })();
149
- message = `${`${message} `.pad(39)} ${stime}`;
150
- if (color)
151
- message = message[color];
152
- console.log(message);
153
- }
154
145
  export function log_line() {
155
146
  console.log('---');
156
147
  }
package/utils.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { Stream, Writable, Transform, type Readable, type Duplex, type TransformCallback } from 'stream'\nimport util from 'util'\n\nimport type Vinyl from 'vinyl'\nimport omit from 'lodash/omit.js'\n\nimport { t } from './i18n/instance.js'\nimport './prototype.js'\n\n\nexport const noop = () => { }\n\n\n/** `230` term 字符宽度 (实际上有 240) */\nexport const output_width = 230\n\n\nexport function set_inspect_options () {\n util.inspect.defaultOptions.maxArrayLength = 40\n util.inspect.defaultOptions.maxStringLength = 10000\n util.inspect.defaultOptions.breakLength = output_width\n util.inspect.defaultOptions.colors = true\n util.inspect.defaultOptions.compact = false\n util.inspect.defaultOptions.getters = true\n util.inspect.defaultOptions.depth = 2\n util.inspect.defaultOptions.sorted = false\n util.inspect.defaultOptions.showProxy = true\n \n util.inspect.styles.number = 'green'\n util.inspect.styles.string = 'cyan'\n util.inspect.styles.boolean = 'blue'\n util.inspect.styles.date = 'magenta'\n util.inspect.styles.special = 'white'\n}\n\n\nexport function assert (assertion: any, message?: string): never | void {\n if (!assertion) {\n debugger\n throw new Error(`${t('断言失败')}: ${ message ? `${message}: ` : '' }${inspect(assertion)}`)\n }\n}\n\n\nexport function dedent (\n templ: TemplateStringsArray | string,\n ...values: any[]\n): string {\n let strings = Array.from(typeof templ === 'string' ? [templ] : templ.raw)\n \n // 1. remove trailing whitespace\n strings[strings.length - 1] = strings[strings.length - 1].replace(\n /\\r?\\n([\\t ]*)$/,\n '',\n )\n \n // 2. find all line breaks to determine the highest common indentation level\n const indent_lengths = strings.reduce<number[]>(\n (arr, str) => {\n const matches = str.match(/\\n[\\t ]+/g)\n if (matches) \n return arr.concat(\n matches.map(match => \n match.length - 1)\n )\n \n return arr\n },\n [],\n )\n \n // 3. remove the common indentation from all strings\n if (indent_lengths.length) {\n const pattern = new RegExp(`\\n[\\t ]{${Math.min(...indent_lengths)}}`, 'g')\n \n strings = strings.map(str => str.replace(pattern, '\\n'))\n }\n \n // 4. remove leading whitespace\n strings[0] = strings[0].replace(/^\\r?\\n/, '')\n \n // 5. perform interpolation\n let string = strings[0]\n \n values.forEach((value, i) => {\n string += value + strings[i + 1]\n })\n \n string += '\\n'\n \n return string\n}\n\n\n/** 数组或 iterable 去重(可按 selector 去重) \n - selector?: 可以是 key (string) 或 (obj: any) => any\n*/\nexport function unique <T> (iterable: T[] | Iterable<T>, selector?: string | ((obj: T) => any)) {\n if (!selector)\n return [...new Set(iterable)]\n \n let map = new Map()\n const is_str_selector = typeof selector === 'string'\n for (const x of iterable)\n map.set(\n is_str_selector ? x[selector] : selector(x),\n x\n )\n \n return [...map.values()]\n}\n\n/** 排序对象中 key 的顺序,返回新的对象 */\nexport function sort_keys <T> (obj: T) {\n return Object.fromEntries(\n Object.entries(obj)\n .sort(([key_l], [key_r]) => \n strcmp(key_l, key_r))\n ) as T\n}\n\n\n/** 字符串字典序比较 */\nexport function strcmp (l: string, r: string) {\n if (l === r) return 0\n if (l < r) return -1\n return 1\n}\n\n\n/** 拼接 TypedArrays 生成一个完整的 Uint8Array */\nexport function concat (arrays: ArrayBufferView[]) {\n let length = 0\n for (const a of arrays)\n length += a.byteLength\n \n let buf = new Uint8Array(length)\n let offset = 0\n for (const a of arrays) {\n const uint8view = new Uint8Array(a.buffer, a.byteOffset, a.byteLength)\n buf.set(uint8view, offset)\n offset += uint8view.byteLength\n }\n \n return buf\n}\n\n\nexport function typed_array_to_buffer (view: ArrayBufferView) {\n return Buffer.from(view.buffer, view.byteOffset, view.byteLength)\n}\n\n\n/** 时间间隔 (milliseconds) 格式化 */\nexport function delta2str (delta: number) {\n if (delta < 1)\n return '0 ms'\n \n // [1, 1000) ms\n if (delta < 1000)\n return `${delta} ms`\n \n // 1.123 s\n if (1000 <= delta && delta < 1000 * 60)\n return `${(delta / 1000).toFixed(1)} s`\n \n // 1 min 12 s [1 min 0s, 60 min)\n const seconds = Math.trunc(delta / 1000)\n \n if (seconds < 60 * 60)\n return `${Math.trunc(seconds / 60)} min ${seconds % 60} s`\n \n const hour = Math.trunc(seconds / 3600)\n \n return `${hour} h ${Math.trunc((seconds - 3600 * hour) / 60)} min ${seconds % 60} s`\n}\n\n\n/** generate random id */\nexport function genid () {\n return Math.random() * 2**53\n}\n\n\nexport class Timer {\n started = new Date().getTime()\n \n ended: number\n \n stop () {\n this.ended = new Date().getTime()\n }\n \n get () {\n if (!this.ended)\n this.stop()\n \n return this.ended - this.started\n }\n \n getstr () {\n return `(${delta2str(this.get())})`\n }\n \n print () {\n console.log(this.getstr())\n }\n}\n\n\nexport function log_section (\n message: string, \n {\n time = false,\n timestamp = false,\n color = undefined,\n }: {\n time?: boolean\n timestamp?: boolean | Date\n color?: 'green' | 'red' | 'yellow'\n } = { }\n) {\n const stime = (() => {\n if (time)\n return delta2str(\n new Date().getTime() - global.started_at.getTime()\n ).pad(4, { position: 'left' })\n if (timestamp)\n if (typeof timestamp === 'object')\n return `${timestamp.to_str()}`\n else\n return `${new Date().to_str()}`\n return ''\n })()\n \n message = `${`${message} `.pad(39)} ${stime}`\n \n if (color)\n message = message[color]\n \n console.log(message)\n}\n\n\nexport function log_line () {\n console.log('---')\n}\n\n\nexport async function delay (milliseconds: number) {\n return new Promise<void>(resolve => {\n setTimeout(resolve, milliseconds)\n })\n}\n\n\nexport async function timeout (milliseconds: number) {\n const error = new Error(t('超时错误'))\n await delay(milliseconds)\n throw error\n}\n\n\n/** https://stackoverflow.com/questions/63297164/how-to-only-accept-arraybuffer-as-parameter */\nexport type StrictArrayBuffer = ArrayBuffer & { buffer?: undefined }\n\n\nexport interface Deferred <TValue> extends Promise<TValue> {\n resolve (value: TValue | PromiseLike<TValue>): void\n reject (reason?: Error): void\n}\n\n/** 创建一个 promise,后续可调用 promise.resolve, promise.reject 方法设置其状态和值 \n - initial?: `undefined` 传入非 undefined 值(包括 null)时直接设置为 resolved 状态 */\nexport function defer <TValue> (initial?: TValue): Deferred<TValue> {\n if (initial === undefined) {\n let resolve: (value: TValue | PromiseLike<TValue>) => void\n let reject: (reason?: Error) => void\n \n let promise = new Promise<TValue>((_resolve, _reject) => {\n resolve = _resolve\n reject = _reject\n })\n \n return Object.assign(promise, { resolve, reject })\n } else\n return Object.assign(Promise.resolve(initial), {\n resolve () { },\n reject () { }\n })\n}\n\n\nexport interface LockedAction <TResource, TResult> {\n (resource: TResource): Promise<TResult>\n}\n\n\n/** @example\n let lock = new Lock(redis)\n \n // 锁定资源后在 action 回调中操作资源,回调 promise 完成后自动释放资源,\n // 三秒内未成功独占资源直接抛出 TimeoutError (开始执行后不受 signal abort 影响)\n await lock.request(async (redis) => {\n const value = await redis.get('key')\n await redis.set('key', value * 2)\n }, AbortSignal.timeout(3000)) \n \n 参考:\n https://developer.mozilla.org/en-US/docs/Web/API/Web_Locks_API \n https://github.com/metarhia/web-locks \n https://www.npmjs.com/package/async-lock */\nexport class Lock <TResource = void> {\n /** 如果操作不需要独占资源,可以直接通过 lock.resource 访问,否则需要通过 await lock.request() 独占资源后再访问 */\n resource: TResource\n \n /** 等待链,新的 await lock.request() 调用会等待当前等待链尾部的 promise 完成,并作为新的尾部 */\n ptail = defer<void>(null)\n \n /** 查询当前资源是否属于被锁定的状态,方便在资源闲置时做一些可选操作(操作前仍需锁定),或者做一些状态展示 */\n locked = false\n \n \n /** 可以不传 resource,表示管理某个抽象或虚拟的资源 */\n constructor (resource?: TResource) {\n this.resource = resource\n }\n \n \n /** 通过 await lock.request() 锁定资源以便独占访问\n 成功返回之后由调用方负责调用 release 方法释放资源\n 在 signal aborted 时抛出错误结束等待,且由内部实现自动释放资源 */\n // async request (action: (resource: TResource) => Promise<void>, signal?: AbortSignal): Promise<void>\n // async request <TResult> (action: <TResult> (resource: TResource) => Promise<TResult>, signal?: AbortSignal): Promise<TResult>\n async request <TResult> (action: LockedAction<TResource, TResult>, signal?: AbortSignal): Promise<TResult> {\n signal?.throwIfAborted()\n \n const ptail = this.ptail\n \n let pcurrent = this.ptail = defer<void>()\n \n this.locked = true\n \n return new Promise<TResult>((resolve, reject) => {\n // 下面两种情况,先发生的决定 request 返回的 promise 状态\n // 不管是否 aborted, 都要等资源被前一次调用释放,先 aborted 只是将控制权交回给调用者,在锁定资源后不执行 action, 直接释放\n \n /** 防止执行过程中 signal abort */\n let executing = false\n \n signal?.addEventListener('abort', () => {\n if (!executing)\n // 这里不能释放锁,需要等 ptail resolve 后拿到资源再释放\n reject(signal.reason)\n }, { once: true })\n \n ptail.then(async () => {\n // 这里已经能保证独占访问资源\n \n // 如果 aborted, 可以理解为独占资源失败,调用者不会使用资源,直接释放\n if (signal?.aborted)\n reject(signal.reason)\n else\n // 由调用者去操作资源\n try {\n executing = true\n resolve(await action(this.resource))\n } catch (error) {\n reject(error)\n }\n \n \n // 下面开始释放锁\n \n // assert(this.locked)\n if (!this.locked)\n reject(new Error(t('尝试释放未锁定的锁,这不应该发生')))\n \n this.locked = false\n \n pcurrent.resolve()\n }\n )})\n }\n}\n\n\n// ------------ text\nexport function has_chinese (str: string) {\n return /[\\u4E00-\\u9FA5]/.test(str)\n}\n\n\nexport function escape_line_feed (str: string) {\n return str.replace(/\\n/g, '\\\\n')\n}\n\n/** util.inspect(obj) \n - options\n - limit?: `10000`\n - omit?: string[] */\nexport function inspect (\n obj: any, \n options: util.InspectOptions & {\n limit?: number\n omit?: string[]\n } = { }\n) {\n if (options.omit)\n obj = omit(obj, [inspect.custom, ...(options.omit || [])])\n \n let text = util.inspect(obj, options)\n \n if (!('limit' in options))\n options.limit = 10000\n if (options.limit && text.length > options.limit)\n return `${text.slice(0, options.limit)}……'\\u001b[39m\\n`\n else\n return text\n}\n\nexport namespace inspect {\n export const custom: typeof util.inspect.custom = util.inspect.custom\n}\n\n\n// ------------------------------------ stream\n/** npm map-stream \n filter will reemit the data if cb(err,pass) pass is truthy \n \n reduce is more tricky \n maybe we want to group the reductions or emit progress updates occasionally \n the most basic reduce just emits one 'data' event after it has recieved 'end'\n \n create an event stream and apply function to each .write, \n emitting each response as data unless it's an empty callback\n */\nexport function map_stream <Out, In = Vinyl> (\n mapper: (obj: In, cb: Function) => any, \n options?: { failures?: boolean }\n) {\n options = options || { }\n \n let inputs = 0,\n outputs = 0,\n ended = false,\n paused = false,\n destroyed = false,\n last_written = 0,\n in_next = false\n \n \n let stream = Object.assign(new Stream(), {\n readable: true, \n writable: true,\n \n write (data?: any) {\n if (ended) throw new Error('map stream is not writable')\n in_next = false\n inputs++\n \n try {\n // catch sync errors and handle them like async errors\n const written = wrapped_mapper(data, inputs, next)\n paused = (written === false)\n return !paused\n } catch (err) {\n // if the callback has been called syncronously, and the error has occured in an listener, throw it again.\n if (in_next)\n throw err\n next(err)\n return !paused\n }\n },\n \n end (data?: any) {\n if (ended) return\n _end(data)\n },\n \n destroy () {\n ended = destroyed = true\n stream.writable = stream.readable = paused = false\n process.nextTick(function () {\n stream.emit('close')\n })\n },\n \n pause () {\n paused = true\n },\n \n resume () {\n paused = false\n }\n })\n \n \n let error_event_name = options.failures ? 'failure' : 'error'\n \n // Items that are not ready to be written yet (because they would come out of order) get stuck in a queue for later.\n let write_queue = { }\n \n \n function queue_data (data, number) {\n let next_to_write = last_written + 1\n \n if (number === next_to_write) {\n // If it's next, and its not undefined write it\n if (data !== undefined) \n stream.emit('data', data)\n \n last_written++\n next_to_write++\n } else \n // Otherwise queue it for later.\n write_queue[number] = data\n \n \n // If the next value is in the queue, write it\n if (Object.prototype.hasOwnProperty.call(write_queue, next_to_write)) {\n let data_to_write = write_queue[next_to_write]\n delete write_queue[next_to_write]\n return queue_data(data_to_write, next_to_write)\n }\n \n outputs++\n if (inputs === outputs) {\n if (paused) {\n paused = false\n stream.emit('drain') // written all the incoming events\n }\n if (ended) _end()\n }\n }\n \n function next (err?: Error, data?: any, number?: number) {\n if (destroyed) return\n in_next = true\n \n if (!err || options.failures)\n queue_data(data, number)\n \n if (err)\n stream.emit(error_event_name, err)\n \n in_next = false\n }\n \n /** Wrap the mapper function by calling its callback with the order number of the item in the stream. */ \n function wrapped_mapper (input, number, callback) {\n return mapper.call(null, input, function (err, data) {\n callback(err, data, number)\n })\n }\n \n function _end (data?: any) {\n // if end was called with args, write it, \n ended = true // write will emit 'end' if ended is true\n stream.writable = false\n if (data !== undefined) \n return queue_data(data, inputs)\n else if (inputs === outputs) { // wait for processing \n stream.readable = false\n stream.emit('end')\n stream.destroy() \n }\n }\n \n return stream as Duplex\n}\n\n\nexport async function stream_to_buffer (stream: Readable) {\n let chunks = [ ]\n for await (const chunk of stream as AsyncIterable<Buffer>)\n chunks.push(chunk)\n return Buffer.concat(chunks)\n}\n\n\nexport async function * stream_to_lines (stream: Readable) {\n let buf = ''\n for await (const chunk of stream as AsyncIterable<string>) {\n let i = 0, j = 0\n for (; (i = chunk.indexOf('\\n', j)) >= 0; ) {\n let line = chunk.slice(j, i)\n if (buf) {\n line = buf + line\n buf = ''\n }\n j = i + 1\n yield line\n }\n buf = chunk.slice(j)\n }\n}\n\n\nexport class WritableMemoryStream extends Writable {\n chunks: Buffer[] = [ ]\n \n pbuffer = defer<Buffer>()\n \n \n constructor () {\n super({ highWaterMark: 2 ** 30, decodeStrings: false })\n }\n \n \n override _write (chunk: Buffer, encoding: BufferEncoding, callback: (error?: Error) => void) {\n this.chunks.push(chunk as Buffer)\n callback()\n }\n \n \n override _writev (chunks: { chunk: any; encoding: BufferEncoding }[], callback: (error?: Error) => void): void {\n for (const { chunk } of chunks)\n this.chunks.push(chunk)\n callback()\n }\n \n \n override _final (callback: (error?: Error) => void): void {\n this.pbuffer.resolve(\n Buffer.concat(this.chunks)\n )\n this.chunks = null\n callback()\n }\n}\n\n\n/** 用 TextDecoder 通过 .pipe 方法持续的解码 process.stdout 等流, \n 主要在 process.ts#start 中使用 \n https://nodejs.org/api/stream.html#implementing-a-transform-stream */\nexport class DecoderStream extends Transform {\n decoder: TextDecoder\n \n \n constructor (encoding: 'gb18030' | 'shift-jis' | 'utf-16le') {\n super({ encoding: 'utf-8' })\n this.decoder = new TextDecoder(encoding)\n }\n \n \n override _transform (chunk: Uint8Array, encoding: BufferEncoding, callback: TransformCallback) {\n assert(chunk instanceof Uint8Array)\n \n const str = this.decoder.decode(chunk, { stream: true })\n \n if (str.length)\n this.push(str, 'utf-8')\n \n callback()\n }\n \n \n override _flush (callback: TransformCallback) {\n const str = this.decoder.decode()\n \n if (str.length)\n this.push(str, 'utf-8')\n \n callback()\n }\n}\n"]}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { Stream, Writable, Transform, type Readable, type Duplex, type TransformCallback } from 'stream'\nimport util from 'util'\n\nimport type Vinyl from 'vinyl'\nimport omit from 'lodash/omit.js'\n\nimport { t } from './i18n/instance.js'\nimport './prototype.js'\n\n\nexport const noop = () => { }\n\n\n/** `230` term 字符宽度 (实际上有 240) */\nexport const output_width = 230\n\n\nexport function set_inspect_options () {\n util.inspect.defaultOptions.maxArrayLength = 40\n util.inspect.defaultOptions.maxStringLength = 10000\n util.inspect.defaultOptions.breakLength = output_width\n util.inspect.defaultOptions.colors = true\n util.inspect.defaultOptions.compact = false\n util.inspect.defaultOptions.getters = true\n util.inspect.defaultOptions.depth = 2\n util.inspect.defaultOptions.sorted = false\n util.inspect.defaultOptions.showProxy = true\n \n util.inspect.styles.number = 'green'\n util.inspect.styles.string = 'cyan'\n util.inspect.styles.boolean = 'blue'\n util.inspect.styles.date = 'magenta'\n util.inspect.styles.special = 'white'\n}\n\n\nexport function assert (assertion: any, message?: string): never | void {\n if (!assertion) {\n debugger\n throw new Error(`${t('断言失败')}: ${ message ? `${message}: ` : '' }${inspect(assertion)}`)\n }\n}\n\n\nexport function dedent (\n templ: TemplateStringsArray | string,\n ...values: any[]\n): string {\n let strings = Array.from(typeof templ === 'string' ? [templ] : templ.raw)\n \n // 1. remove trailing whitespace\n strings[strings.length - 1] = strings[strings.length - 1].replace(\n /\\r?\\n([\\t ]*)$/,\n '',\n )\n \n // 2. find all line breaks to determine the highest common indentation level\n const indent_lengths = strings.reduce<number[]>(\n (arr, str) => {\n const matches = str.match(/\\n[\\t ]+/g)\n if (matches) \n return arr.concat(\n matches.map(match => \n match.length - 1)\n )\n \n return arr\n },\n [],\n )\n \n // 3. remove the common indentation from all strings\n if (indent_lengths.length) {\n const pattern = new RegExp(`\\n[\\t ]{${Math.min(...indent_lengths)}}`, 'g')\n \n strings = strings.map(str => str.replace(pattern, '\\n'))\n }\n \n // 4. remove leading whitespace\n strings[0] = strings[0].replace(/^\\r?\\n/, '')\n \n // 5. perform interpolation\n let string = strings[0]\n \n values.forEach((value, i) => {\n string += value + strings[i + 1]\n })\n \n string += '\\n'\n \n return string\n}\n\n\n/** 数组或 iterable 去重(可按 selector 去重) \n - selector?: 可以是 key (string) 或 (obj: any) => any\n*/\nexport function unique <T> (iterable: T[] | Iterable<T>, selector?: string | ((obj: T) => any)) {\n if (!selector)\n return [...new Set(iterable)]\n \n let map = new Map()\n const is_str_selector = typeof selector === 'string'\n for (const x of iterable)\n map.set(\n is_str_selector ? x[selector] : selector(x),\n x\n )\n \n return [...map.values()]\n}\n\n/** 排序对象中 key 的顺序,返回新的对象 */\nexport function sort_keys <T> (obj: T) {\n return Object.fromEntries(\n Object.entries(obj)\n .sort(([key_l], [key_r]) => \n strcmp(key_l, key_r))\n ) as T\n}\n\n\n/** 字符串字典序比较 */\nexport function strcmp (l: string, r: string) {\n if (l === r) return 0\n if (l < r) return -1\n return 1\n}\n\n\n/** 拼接 TypedArrays 生成一个完整的 Uint8Array */\nexport function concat (arrays: ArrayBufferView[]) {\n let length = 0\n for (const a of arrays)\n length += a.byteLength\n \n let buf = new Uint8Array(length)\n let offset = 0\n for (const a of arrays) {\n const uint8view = new Uint8Array(a.buffer, a.byteOffset, a.byteLength)\n buf.set(uint8view, offset)\n offset += uint8view.byteLength\n }\n \n return buf\n}\n\n\nexport function typed_array_to_buffer (view: ArrayBufferView) {\n return Buffer.from(view.buffer, view.byteOffset, view.byteLength)\n}\n\n\n/** 时间间隔 (milliseconds) 格式化 */\nexport function delta2str (delta: number) {\n if (delta < 1)\n return '0 ms'\n \n // [1, 1000) ms\n if (delta < 1000)\n return `${delta} ms`\n \n // 1.123 s\n if (1000 <= delta && delta < 1000 * 60)\n return `${(delta / 1000).toFixed(1)} s`\n \n // 1 min 12 s [1 min 0s, 60 min)\n const seconds = Math.trunc(delta / 1000)\n \n if (seconds < 60 * 60)\n return `${Math.trunc(seconds / 60)} min ${seconds % 60} s`\n \n const hour = Math.trunc(seconds / 3600)\n \n return `${hour} h ${Math.trunc((seconds - 3600 * hour) / 60)} min ${seconds % 60} s`\n}\n\n\n/** generate random id */\nexport function genid () {\n return Math.random() * 2**53\n}\n\n\nexport class Timer {\n started = new Date().getTime()\n \n ended: number\n \n /** 停止秒表,保存读数 */\n stop () {\n this.ended = new Date().getTime()\n }\n \n /** 如果秒表未停止,获取当前秒表读数;\n 如果秒表已停止,获取停止时的秒表读数; */\n get () {\n return (this.ended || new Date().getTime()) - this.started\n }\n \n /** 获取时间表示字符串,如 1.2 s \n - bracket?: `true` 字符串前后加上括号,如 (1.2 s) */\n getstr (bracket = false) {\n let s = delta2str(this.get())\n if (bracket)\n return s.bracket()\n else\n return s\n }\n \n print () {\n console.log(this.getstr(true))\n }\n}\n\n\nexport function log_line () {\n console.log('---')\n}\n\n\nexport async function delay (milliseconds: number) {\n return new Promise<void>(resolve => {\n setTimeout(resolve, milliseconds)\n })\n}\n\n\nexport async function timeout (milliseconds: number) {\n const error = new Error(t('超时错误'))\n await delay(milliseconds)\n throw error\n}\n\n\n/** https://stackoverflow.com/questions/63297164/how-to-only-accept-arraybuffer-as-parameter */\nexport type StrictArrayBuffer = ArrayBuffer & { buffer?: undefined }\n\n\nexport interface Deferred <TValue> extends Promise<TValue> {\n resolve (value: TValue | PromiseLike<TValue>): void\n reject (reason?: Error): void\n}\n\n/** 创建一个 promise,后续可调用 promise.resolve, promise.reject 方法设置其状态和值 \n - initial?: `undefined` 传入非 undefined 值(包括 null)时直接设置为 resolved 状态 */\nexport function defer <TValue> (initial?: TValue): Deferred<TValue> {\n if (initial === undefined) {\n let resolve: (value: TValue | PromiseLike<TValue>) => void\n let reject: (reason?: Error) => void\n \n let promise = new Promise<TValue>((_resolve, _reject) => {\n resolve = _resolve\n reject = _reject\n })\n \n return Object.assign(promise, { resolve, reject })\n } else\n return Object.assign(Promise.resolve(initial), {\n resolve () { },\n reject () { }\n })\n}\n\n\nexport interface LockedAction <TResource, TResult> {\n (resource: TResource): Promise<TResult>\n}\n\n\n/** @example\n let lock = new Lock(redis)\n \n // 锁定资源后在 action 回调中操作资源,回调 promise 完成后自动释放资源,\n // 三秒内未成功独占资源直接抛出 TimeoutError (开始执行后不受 signal abort 影响)\n await lock.request(async (redis) => {\n const value = await redis.get('key')\n await redis.set('key', value * 2)\n }, AbortSignal.timeout(3000)) \n \n 参考:\n https://developer.mozilla.org/en-US/docs/Web/API/Web_Locks_API \n https://github.com/metarhia/web-locks \n https://www.npmjs.com/package/async-lock */\nexport class Lock <TResource = void> {\n /** 如果操作不需要独占资源,可以直接通过 lock.resource 访问,否则需要通过 await lock.request() 独占资源后再访问 */\n resource: TResource\n \n /** 等待链,新的 await lock.request() 调用会等待当前等待链尾部的 promise 完成,并作为新的尾部 */\n ptail = defer<void>(null)\n \n /** 查询当前资源是否属于被锁定的状态,方便在资源闲置时做一些可选操作(操作前仍需锁定),或者做一些状态展示 */\n locked = false\n \n \n /** 可以不传 resource,表示管理某个抽象或虚拟的资源 */\n constructor (resource?: TResource) {\n this.resource = resource\n }\n \n \n /** 通过 await lock.request() 锁定资源以便独占访问\n 成功返回之后由调用方负责调用 release 方法释放资源\n 在 signal aborted 时抛出错误结束等待,且由内部实现自动释放资源 */\n // async request (action: (resource: TResource) => Promise<void>, signal?: AbortSignal): Promise<void>\n // async request <TResult> (action: <TResult> (resource: TResource) => Promise<TResult>, signal?: AbortSignal): Promise<TResult>\n async request <TResult> (action: LockedAction<TResource, TResult>, signal?: AbortSignal): Promise<TResult> {\n signal?.throwIfAborted()\n \n const ptail = this.ptail\n \n let pcurrent = this.ptail = defer<void>()\n \n this.locked = true\n \n return new Promise<TResult>((resolve, reject) => {\n // 下面两种情况,先发生的决定 request 返回的 promise 状态\n // 不管是否 aborted, 都要等资源被前一次调用释放,先 aborted 只是将控制权交回给调用者,在锁定资源后不执行 action, 直接释放\n \n /** 防止执行过程中 signal abort */\n let executing = false\n \n signal?.addEventListener('abort', () => {\n if (!executing)\n // 这里不能释放锁,需要等 ptail resolve 后拿到资源再释放\n reject(signal.reason)\n }, { once: true })\n \n ptail.then(async () => {\n // 这里已经能保证独占访问资源\n \n // 如果 aborted, 可以理解为独占资源失败,调用者不会使用资源,直接释放\n if (signal?.aborted)\n reject(signal.reason)\n else\n // 由调用者去操作资源\n try {\n executing = true\n resolve(await action(this.resource))\n } catch (error) {\n reject(error)\n }\n \n \n // 下面开始释放锁\n \n // assert(this.locked)\n if (!this.locked)\n reject(new Error(t('尝试释放未锁定的锁,这不应该发生')))\n \n this.locked = false\n \n pcurrent.resolve()\n }\n )})\n }\n}\n\n\n// ------------ text\nexport function has_chinese (str: string) {\n return /[\\u4E00-\\u9FA5]/.test(str)\n}\n\n\nexport function escape_line_feed (str: string) {\n return str.replace(/\\n/g, '\\\\n')\n}\n\n/** util.inspect(obj) \n - options\n - limit?: `10000`\n - omit?: string[] */\nexport function inspect (\n obj: any, \n options: util.InspectOptions & {\n limit?: number\n omit?: string[]\n } = { }\n) {\n if (options.omit)\n obj = omit(obj, [inspect.custom, ...(options.omit || [])])\n \n let text = util.inspect(obj, options)\n \n if (!('limit' in options))\n options.limit = 10000\n if (options.limit && text.length > options.limit)\n return `${text.slice(0, options.limit)}……'\\u001b[39m\\n`\n else\n return text\n}\n\nexport namespace inspect {\n export const custom: typeof util.inspect.custom = util.inspect.custom\n}\n\n\n// ------------------------------------ stream\n/** npm map-stream \n filter will reemit the data if cb(err,pass) pass is truthy \n \n reduce is more tricky \n maybe we want to group the reductions or emit progress updates occasionally \n the most basic reduce just emits one 'data' event after it has recieved 'end'\n \n create an event stream and apply function to each .write, \n emitting each response as data unless it's an empty callback\n */\nexport function map_stream <Out, In = Vinyl> (\n mapper: (obj: In, cb: Function) => any, \n options?: { failures?: boolean }\n) {\n options = options || { }\n \n let inputs = 0,\n outputs = 0,\n ended = false,\n paused = false,\n destroyed = false,\n last_written = 0,\n in_next = false\n \n \n let stream = Object.assign(new Stream(), {\n readable: true, \n writable: true,\n \n write (data?: any) {\n if (ended) throw new Error('map stream is not writable')\n in_next = false\n inputs++\n \n try {\n // catch sync errors and handle them like async errors\n const written = wrapped_mapper(data, inputs, next)\n paused = (written === false)\n return !paused\n } catch (err) {\n // if the callback has been called syncronously, and the error has occured in an listener, throw it again.\n if (in_next)\n throw err\n next(err)\n return !paused\n }\n },\n \n end (data?: any) {\n if (ended) return\n _end(data)\n },\n \n destroy () {\n ended = destroyed = true\n stream.writable = stream.readable = paused = false\n process.nextTick(function () {\n stream.emit('close')\n })\n },\n \n pause () {\n paused = true\n },\n \n resume () {\n paused = false\n }\n })\n \n \n let error_event_name = options.failures ? 'failure' : 'error'\n \n // Items that are not ready to be written yet (because they would come out of order) get stuck in a queue for later.\n let write_queue = { }\n \n \n function queue_data (data, number) {\n let next_to_write = last_written + 1\n \n if (number === next_to_write) {\n // If it's next, and its not undefined write it\n if (data !== undefined) \n stream.emit('data', data)\n \n last_written++\n next_to_write++\n } else \n // Otherwise queue it for later.\n write_queue[number] = data\n \n \n // If the next value is in the queue, write it\n if (Object.prototype.hasOwnProperty.call(write_queue, next_to_write)) {\n let data_to_write = write_queue[next_to_write]\n delete write_queue[next_to_write]\n return queue_data(data_to_write, next_to_write)\n }\n \n outputs++\n if (inputs === outputs) {\n if (paused) {\n paused = false\n stream.emit('drain') // written all the incoming events\n }\n if (ended) _end()\n }\n }\n \n function next (err?: Error, data?: any, number?: number) {\n if (destroyed) return\n in_next = true\n \n if (!err || options.failures)\n queue_data(data, number)\n \n if (err)\n stream.emit(error_event_name, err)\n \n in_next = false\n }\n \n /** Wrap the mapper function by calling its callback with the order number of the item in the stream. */ \n function wrapped_mapper (input, number, callback) {\n return mapper.call(null, input, function (err, data) {\n callback(err, data, number)\n })\n }\n \n function _end (data?: any) {\n // if end was called with args, write it, \n ended = true // write will emit 'end' if ended is true\n stream.writable = false\n if (data !== undefined) \n return queue_data(data, inputs)\n else if (inputs === outputs) { // wait for processing \n stream.readable = false\n stream.emit('end')\n stream.destroy() \n }\n }\n \n return stream as Duplex\n}\n\n\nexport async function stream_to_buffer (stream: Readable) {\n let chunks = [ ]\n for await (const chunk of stream as AsyncIterable<Buffer>)\n chunks.push(chunk)\n return Buffer.concat(chunks)\n}\n\n\nexport async function * stream_to_lines (stream: Readable) {\n let buf = ''\n for await (const chunk of stream as AsyncIterable<string>) {\n let i = 0, j = 0\n for (; (i = chunk.indexOf('\\n', j)) >= 0; ) {\n let line = chunk.slice(j, i)\n if (buf) {\n line = buf + line\n buf = ''\n }\n j = i + 1\n yield line\n }\n buf = chunk.slice(j)\n }\n}\n\n\nexport class WritableMemoryStream extends Writable {\n chunks: Buffer[] = [ ]\n \n pbuffer = defer<Buffer>()\n \n \n constructor () {\n super({ highWaterMark: 2 ** 30, decodeStrings: false })\n }\n \n \n override _write (chunk: Buffer, encoding: BufferEncoding, callback: (error?: Error) => void) {\n this.chunks.push(chunk as Buffer)\n callback()\n }\n \n \n override _writev (chunks: { chunk: any; encoding: BufferEncoding }[], callback: (error?: Error) => void): void {\n for (const { chunk } of chunks)\n this.chunks.push(chunk)\n callback()\n }\n \n \n override _final (callback: (error?: Error) => void): void {\n this.pbuffer.resolve(\n Buffer.concat(this.chunks)\n )\n this.chunks = null\n callback()\n }\n}\n\n\n/** 用 TextDecoder 通过 .pipe 方法持续的解码 process.stdout 等流, \n 主要在 process.ts#start 中使用 \n https://nodejs.org/api/stream.html#implementing-a-transform-stream */\nexport class DecoderStream extends Transform {\n decoder: TextDecoder\n \n \n constructor (encoding: 'gb18030' | 'shift-jis' | 'utf-16le') {\n super({ encoding: 'utf-8' })\n this.decoder = new TextDecoder(encoding)\n }\n \n \n override _transform (chunk: Uint8Array, encoding: BufferEncoding, callback: TransformCallback) {\n assert(chunk instanceof Uint8Array)\n \n const str = this.decoder.decode(chunk, { stream: true })\n \n if (str.length)\n this.push(str, 'utf-8')\n \n callback()\n }\n \n \n override _flush (callback: TransformCallback) {\n const str = this.decoder.decode()\n \n if (str.length)\n this.push(str, 'utf-8')\n \n callback()\n }\n}\n"]}