node-karin 1.15.5 → 1.16.1

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.
Files changed (89) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/dist/adapter-BqlH3u3X.mjs +218 -0
  3. package/dist/app-DdMQbBEY.mjs +4109 -0
  4. package/dist/cache-CPcPeo6N.mjs +163 -0
  5. package/dist/chunk-NzVPYdc1.mjs +21 -0
  6. package/dist/cli/index.cjs +10900 -1
  7. package/dist/cli/index.d.ts +1 -1
  8. package/dist/cli/index.mjs +10770 -10224
  9. package/dist/file-ZGuqNDd-.mjs +15987 -0
  10. package/dist/file-dGy9of8-.mjs +268 -0
  11. package/dist/fsSync-Cf5MWILk.mjs +65 -0
  12. package/dist/index.d.ts +12235 -12738
  13. package/dist/index.mjs +2054 -25247
  14. package/dist/internal-DupfycKE.mjs +597 -0
  15. package/dist/kv-DZp4UIxg.mjs +192 -0
  16. package/dist/module/art-template.d.ts +2 -13
  17. package/dist/module/art-template.mjs +3 -1
  18. package/dist/module/axios.d.ts +3 -2
  19. package/dist/module/axios.mjs +5 -2
  20. package/dist/module/chalk.d.ts +3 -2
  21. package/dist/module/chalk.mjs +5 -2
  22. package/dist/module/chokidar.d.ts +3 -2
  23. package/dist/module/chokidar.mjs +5 -2
  24. package/dist/module/express.d.ts +2 -1
  25. package/dist/module/express.mjs +3 -1
  26. package/dist/module/lodash.d.ts +2 -1
  27. package/dist/module/lodash.mjs +3 -1
  28. package/dist/module/log4js.d.ts +3 -2
  29. package/dist/module/log4js.mjs +5 -2
  30. package/dist/module/moment.d.ts +2 -1
  31. package/dist/module/moment.mjs +3 -1
  32. package/dist/module/node-schedule.d.ts +3 -2
  33. package/dist/module/node-schedule.mjs +5 -2
  34. package/dist/module/redis.d.ts +3 -2
  35. package/dist/module/redis.mjs +5 -2
  36. package/dist/module/sqlite3.d.ts +3 -2
  37. package/dist/module/sqlite3.mjs +5 -2
  38. package/dist/module/ws.d.ts +3 -2
  39. package/dist/module/ws.mjs +5 -2
  40. package/dist/module/yaml.d.ts +3 -2
  41. package/dist/module/yaml.mjs +5 -2
  42. package/dist/queue-CnKedaZA.mjs +70 -0
  43. package/dist/redis-aLJ7wbJH.mjs +1556 -0
  44. package/dist/render-DPqueDZr.mjs +170 -0
  45. package/dist/root.d.ts +46 -46
  46. package/dist/root.mjs +136 -93
  47. package/dist/router-zPSN9-tY.mjs +124 -0
  48. package/dist/server-DT64D-m-.mjs +38 -0
  49. package/dist/snapka-BTlnZOyI.mjs +450 -0
  50. package/dist/sqlite-Dcj9jlW9.mjs +307 -0
  51. package/dist/start/app.d.ts +1 -1
  52. package/dist/start/app.mjs +14 -7
  53. package/dist/start/index.d.ts +1 -1
  54. package/dist/start/index.mjs +325 -656
  55. package/dist/template-Djk6y0uC.mjs +133 -0
  56. package/dist/terminalManager-Lxa8Sm06.mjs +783 -0
  57. package/dist/uptime-C121X_rq.mjs +210 -0
  58. package/dist/web/{CompressaPRO-GX.woff2.br → CompressaPRO-GX.woff2} +0 -0
  59. package/dist/web/assets/css/style-CBB8wM_W.css +14880 -0
  60. package/dist/web/assets/js/entry-Blf4Trpx.js +258540 -0
  61. package/dist/web/{googleapis.woff2.br → googleapis.woff2} +0 -0
  62. package/dist/web/index.html +2 -15
  63. package/dist/web/karin.png +0 -0
  64. package/dist/web/sha256.min.js +9 -0
  65. package/dist/ws-BLDoC2gV.mjs +80 -0
  66. package/dist/ws-CcoWd3Ar.mjs +106 -0
  67. package/package.json +7 -7
  68. package/dist/global.d.d.ts +0 -68
  69. package/dist/types-hAhbXJDZ.d.ts +0 -109
  70. package/dist/web/assets/css/components-ep7vm38G.css +0 -1
  71. package/dist/web/assets/css/index-Dadvd9mn.css.br +0 -0
  72. package/dist/web/assets/css/vendor-editor-CFbL2ovg.css.br +0 -0
  73. package/dist/web/assets/css/vendor-others-ZgkIHsf0.css +0 -1
  74. package/dist/web/assets/js/components-CU2xw4lY.js.br +0 -0
  75. package/dist/web/assets/js/entry-Dvb7eYLE.js.br +0 -0
  76. package/dist/web/assets/js/hooks-CRfhs4ON.js.br +0 -0
  77. package/dist/web/assets/js/page-404.tsx-DYMd_RI_.js +0 -1
  78. package/dist/web/assets/js/page-dashboard-CG60V_Z-.js.br +0 -0
  79. package/dist/web/assets/js/page-loading.tsx-wY8a9me3.js.br +0 -0
  80. package/dist/web/assets/js/page-login.tsx-B54ZOEZB.js.br +0 -0
  81. package/dist/web/assets/js/utils-C9nWTSuo.js +0 -2
  82. package/dist/web/assets/js/vendor-editor-BmqYP7lh.js.br +0 -0
  83. package/dist/web/assets/js/vendor-heroui-ClBCy2zk.js.br +0 -0
  84. package/dist/web/assets/js/vendor-others-6GiMrjd4.js.br +0 -0
  85. package/dist/web/assets/js/vendor-react-Dc9jdQiK.js.br +0 -0
  86. package/dist/web/assets/js/vendor-ui-utils-D0xkboLL.js.br +0 -0
  87. package/dist/web/assets/js/vendor-visual-saF8KLH_.js.br +0 -0
  88. package/dist/web/karin.png.br +0 -0
  89. package/dist/web/sha256.min.js.br +0 -0
@@ -0,0 +1,597 @@
1
+ import { t as __exportAll } from "./chunk-NzVPYdc1.mjs";
2
+ import { f as sep } from "./file-dGy9of8-.mjs";
3
+ import path from "node:path";
4
+ import fs from "node:fs";
5
+ import { fileURLToPath } from "node:url";
6
+ import lodash from "lodash";
7
+ import { EventEmitter } from "node:events";
8
+ import os from "node:os";
9
+
10
+ //#region src/utils/fs/path.ts
11
+ /**
12
+ * @description 根据文件后缀名从指定路径下读取符合要求的文件
13
+ * @param path - 路径
14
+ * @param ext - 后缀名、或后缀名列表
15
+ * @param returnType - 返回类型 `name:文件名` `rel:相对路径` `abs:绝对路径`
16
+ * @example
17
+ * ```ts
18
+ * filesByExt('./plugins/karin-plugin-test', '.js')
19
+ * // -> ['1.js', '2.js']
20
+ * filesByExt('./plugins', ['.js', '.ts'], 'name')
21
+ * // -> ['1.js', '2.js', '3.ts']
22
+ * filesByExt('./plugins', '.js', 'rel')
23
+ * // -> ['plugins/1.js', 'plugins/2.js']
24
+ * filesByExt('./plugins', '.js', 'abs')
25
+ * // -> ['C:/Users/karin/plugins/1.js', 'C:/Users/karin/plugins/2.js']
26
+ * ```
27
+ */
28
+ const filesByExt = (filePath, ext, returnType = "name") => {
29
+ if (!fs.existsSync(filePath) || !fs.statSync(filePath).isDirectory()) return [];
30
+ const files = fs.readdirSync(filePath, { withFileTypes: true });
31
+ const list = [];
32
+ if (!Array.isArray(ext)) ext = [ext];
33
+ const allFiles = (dir, entry) => {
34
+ /** 如果是目录则递归查找 */
35
+ if (entry.isDirectory()) {
36
+ const subFiles = filesByExt(path.join(dir, entry.name), ext, returnType);
37
+ list.push(...subFiles);
38
+ } else if (ext.includes(path.extname(entry.name))) {
39
+ /** 如果是文件则添加到列表 */
40
+ if (returnType === "name") list.push(entry.name);
41
+ else if (returnType === "rel") {
42
+ const file = path.resolve(dir, entry.name);
43
+ list.push(path.relative(process.cwd(), file));
44
+ } else if (returnType === "abs") list.push(formatPath(path.resolve(dir, entry.name)));
45
+ }
46
+ };
47
+ files.forEach((entry) => allFiles(filePath, entry));
48
+ return list;
49
+ };
50
+ /**
51
+ * @description 分割路径为文件夹路径和文件名
52
+ * @param filePath - 路径
53
+ * @returns - 文件夹路径和文件名
54
+ * @example
55
+ * ```ts
56
+ * splitPath('C:/Users/admin/1.txt')
57
+ * // -> { dirname: 'C:/Users/admin', basename: '1.txt' }
58
+ * ```
59
+ */
60
+ const splitPath = (filePath) => {
61
+ return {
62
+ dirname: path.dirname(filePath).replace(sep, ""),
63
+ basename: path.basename(filePath)
64
+ };
65
+ };
66
+ /**
67
+ * @description 去掉相对路径的前缀和后缀
68
+ * @param filePath - 相对路径路径
69
+ * @example
70
+ * ```ts
71
+ * getRelPath('./plugins/karin-plugin-example/index.ts')
72
+ * // -> 'plugins/karin-plugin-example/index.ts'
73
+ * ```
74
+ */
75
+ const getRelPath = (filePath) => filePath.replace(/\\+/g, "/").replace(/\.+\/+|\/+$/g, "");
76
+ /**
77
+ * 根据传入的 import.meta.url 计算相对于项目根目录的路径,返回需要的 '../' 层级。
78
+ * @param url - import.meta.url
79
+ * @returns 相对路径的层级数量,用 '../' 表示
80
+ * @example
81
+ * ```ts
82
+ * // 在 plugins/karin-plugin-example/index.ts 中使用
83
+ * urlToPath(import.meta.url)
84
+ * // -> '../../'
85
+ * ```
86
+ */
87
+ const urlToPath = (url) => {
88
+ const filePath = fileURLToPath(url);
89
+ /** 相对路径的层级数量 */
90
+ const upLevelsCount = path.relative(path.dirname(filePath), process.cwd()).split(path.sep).length;
91
+ return lodash.repeat("../", upLevelsCount);
92
+ };
93
+ /**
94
+ * @description 检查目标路径是否处于根路径下
95
+ * @param root 根路径
96
+ * @param target 目标路径
97
+ * @param isAbs 是否将传入的路径转为绝对路径
98
+ * @returns 返回布尔值
99
+ */
100
+ const isSubPath = (root, target, isAbs = true) => {
101
+ if (isAbs) {
102
+ root = path.resolve(root);
103
+ target = path.resolve(target);
104
+ }
105
+ /** 相对路径 */
106
+ const relative = path.relative(root, target);
107
+ /** 检查是否以 `..` 开头或是否为空路径 如果是则代表目标路径不处于根路径下 */
108
+ return relative && !relative.startsWith("..") && !path.isAbsolute(relative);
109
+ };
110
+ /**
111
+ * @description 将路径统一格式
112
+ * - 绝对路径
113
+ * - 统一分隔符`/`
114
+ * @param filePath - 路径
115
+ * @returns 统一格式后的路径
116
+ */
117
+ const formatPath = (filePath) => {
118
+ return path.resolve(filePath).replace(/\\/g, "/");
119
+ };
120
+ /**
121
+ * @description 比较两个路径是否相同
122
+ * @param path1 - 第一个路径
123
+ * @param path2 - 第二个路径
124
+ * @returns 是否相同
125
+ * @example
126
+ * ```ts
127
+ * isPathEqual('C:\\Users\\admin', 'C:/Users/admin')
128
+ * // -> true
129
+ * isPathEqual('./folder', 'folder')
130
+ * // -> true
131
+ * ```
132
+ */
133
+ const isPathEqual = (path1, path2) => {
134
+ /** 先直接判断 */
135
+ if (path1 === path2) return true;
136
+ /** 格式化后第二次比较 */
137
+ path1 = formatPath(path1);
138
+ path2 = formatPath(path2);
139
+ if (path1 === path2) return true;
140
+ /** 判断是否为windows */
141
+ if (process.platform === "win32") return path1.toLowerCase() === path2.toLowerCase();
142
+ return false;
143
+ };
144
+
145
+ //#endregion
146
+ //#region src/plugin/system/cache.ts
147
+ /** 缓存 */
148
+ const cache = {
149
+ index: {},
150
+ accept: [],
151
+ command: [],
152
+ task: [],
153
+ button: [],
154
+ handler: {},
155
+ missing: /* @__PURE__ */ new Map(),
156
+ watcher: /* @__PURE__ */ new Map(),
157
+ count: {
158
+ accept: 0,
159
+ command: 0,
160
+ task: 0,
161
+ button: 0,
162
+ handler: {
163
+ key: 0,
164
+ fnc: 0
165
+ }
166
+ },
167
+ static: []
168
+ };
169
+
170
+ //#endregion
171
+ //#region src/utils/fs/static.ts
172
+ /**
173
+ * @description 传入一个文件路径,检查是否是静态资源中的文件
174
+ * @param filePath 文件路径
175
+ * @returns 是否是静态资源中的文件
176
+ */
177
+ const isPublic = (filePath) => {
178
+ try {
179
+ for (const item of cache.static) if (isSubPath(item, filePath)) return true;
180
+ return false;
181
+ } catch (error) {
182
+ logger.error(error);
183
+ return false;
184
+ }
185
+ };
186
+
187
+ //#endregion
188
+ //#region src/utils/fs/key.ts
189
+ var key_exports = /* @__PURE__ */ __exportAll({
190
+ BOT_CONNECT: () => BOT_CONNECT,
191
+ BOT_DISCONNECT: () => BOT_DISCONNECT,
192
+ EVENT_COUNT: () => EVENT_COUNT,
193
+ FILE_CHANGE: () => FILE_CHANGE,
194
+ RECV_MSG: () => RECV_MSG,
195
+ SEND_MSG: () => SEND_MSG,
196
+ WS_CLOSE: () => WS_CLOSE,
197
+ WS_CLOSE_ONEBOT: () => WS_CLOSE_ONEBOT,
198
+ WS_CLOSE_PUPPETEER: () => WS_CLOSE_PUPPETEER,
199
+ WS_CLOSE_SANDBOX: () => WS_CLOSE_SANDBOX,
200
+ WS_CONNECTION: () => WS_CONNECTION,
201
+ WS_CONNECTION_ONEBOT: () => WS_CONNECTION_ONEBOT,
202
+ WS_CONNECTION_PUPPETEER: () => WS_CONNECTION_PUPPETEER,
203
+ WS_CONNECTION_SANDBOX: () => WS_CONNECTION_SANDBOX,
204
+ WS_CONNECTION_TERMINAL: () => WS_CONNECTION_TERMINAL,
205
+ WS_SNAPKA: () => WS_SNAPKA
206
+ });
207
+ /** 收到消息 */
208
+ const RECV_MSG = "karin:count:recv";
209
+ /** 发送消息 */
210
+ const SEND_MSG = "karin:count:send";
211
+ /** 事件调用 */
212
+ const EVENT_COUNT = "karin:count:fnc";
213
+ /** 文件变动 */
214
+ const FILE_CHANGE = "karin:file:change";
215
+ /** 传递ws连接 */
216
+ const WS_CONNECTION = "ws:connection";
217
+ /** 传递onebot ws连接 */
218
+ const WS_CONNECTION_ONEBOT = "ws:connection:onebot";
219
+ /** 传递puppeteer ws连接 */
220
+ const WS_CONNECTION_PUPPETEER = "ws:connection:puppeteer";
221
+ /** 传递sandbox ws连接 */
222
+ const WS_CONNECTION_SANDBOX = "ws:connection:sandbox";
223
+ /** 传递虚拟终端 ws连接 */
224
+ const WS_CONNECTION_TERMINAL = "ws:connection:terminal";
225
+ /** 传递ws关闭 */
226
+ const WS_CLOSE = "ws:close";
227
+ /** 传递onebot ws关闭 */
228
+ const WS_CLOSE_ONEBOT = "ws:close:onebot";
229
+ /** 传递puppeteer ws关闭 */
230
+ const WS_CLOSE_PUPPETEER = "ws:close:puppeteer";
231
+ /** 传递sandbox ws关闭 */
232
+ const WS_CLOSE_SANDBOX = "ws:close:sandbox";
233
+ /** 传递 snapka ws连接 */
234
+ const WS_SNAPKA = "ws:connection:snapka";
235
+ /** Bot连接成功 */
236
+ const BOT_CONNECT = "bot.connect";
237
+ /** Bot连接断开 */
238
+ const BOT_DISCONNECT = "bot.disconnect";
239
+
240
+ //#endregion
241
+ //#region src/core/internal/listeners.ts
242
+ /** 类型化事件监听器 */
243
+ var TypedListeners = class extends EventEmitter {
244
+ /**
245
+ * 注册事件监听器
246
+ * @param event 事件名称
247
+ * @param listener 监听器函数
248
+ */
249
+ on(event, listener) {
250
+ return super.on(event, listener);
251
+ }
252
+ /**
253
+ * 注册一次性事件监听器
254
+ * @param event 事件名称
255
+ * @param listener 监听器函数
256
+ */
257
+ once(event, listener) {
258
+ return super.once(event, listener);
259
+ }
260
+ /**
261
+ * 移除事件监听器
262
+ * @param event 事件名称
263
+ * @param listener 监听器函数
264
+ */
265
+ off(event, listener) {
266
+ return super.off(event, listener);
267
+ }
268
+ /**
269
+ * 触发事件
270
+ * @param event 事件名称
271
+ * @param args 事件参数
272
+ */
273
+ emit(event, ...args) {
274
+ return super.emit(event, ...args);
275
+ }
276
+ /**
277
+ * 获取事件监听器列表
278
+ * @param event 事件名称
279
+ */
280
+ listeners(event) {
281
+ return super.listeners(event);
282
+ }
283
+ /**
284
+ * 移除所有事件监听器
285
+ * @param event 事件名称
286
+ * @returns this
287
+ */
288
+ removeAllListeners(event) {
289
+ super.removeAllListeners(event);
290
+ return this;
291
+ }
292
+ /**
293
+ * 设置最大监听器数量
294
+ * @param n 最大监听器数量
295
+ * @returns this
296
+ */
297
+ setMaxListeners(n) {
298
+ super.setMaxListeners(n);
299
+ return this;
300
+ }
301
+ /**
302
+ * 获取最大监听器数量
303
+ * @returns 最大监听器数量
304
+ */
305
+ getMaxListeners() {
306
+ return super.getMaxListeners();
307
+ }
308
+ /**
309
+ * 添加事件监听器
310
+ * @param event 事件名称
311
+ * @param listener 监听器函数
312
+ */
313
+ addListener(event, listener) {
314
+ return super.addListener(event, listener);
315
+ }
316
+ /**
317
+ * 获取事件监听器数量
318
+ * @param event 事件名称
319
+ * @returns 监听器数量
320
+ */
321
+ listenerCount(event) {
322
+ return super.listenerCount(event);
323
+ }
324
+ /**
325
+ * 返回已注册的事件名称数组
326
+ * @param event 事件名称
327
+ * @returns 监听器数量
328
+ */
329
+ eventNames() {
330
+ return super.eventNames();
331
+ }
332
+ /**
333
+ * 返回指定事件的原始监听器数组(包括一次性监听器)
334
+ * @param event 事件名称
335
+ * @returns 监听器数量
336
+ */
337
+ rawListeners(event) {
338
+ return super.rawListeners(event);
339
+ }
340
+ /**
341
+ * 为指定事件添加监听器,但将其添加到监听器数组的开头
342
+ * @param event 事件名称
343
+ * @returns 监听器数量
344
+ */
345
+ prependListener(event, listener) {
346
+ return super.prependListener(event, listener);
347
+ }
348
+ /**
349
+ * 为指定事件添加一次性监听器,并将其添加到监听器数组的开头
350
+ * @param event 事件名称
351
+ * @returns 监听器数量
352
+ */
353
+ prependOnceListener(event, listener) {
354
+ return super.prependOnceListener(event, listener);
355
+ }
356
+ /**
357
+ * 移除事件监听器
358
+ * @param event 事件名称
359
+ * @param listener 监听器函数
360
+ */
361
+ removeListener(event, listener) {
362
+ return super.removeListener(event, listener);
363
+ }
364
+ };
365
+ /**
366
+ * @internal
367
+ * @description 内部事件监听器
368
+ */
369
+ const listeners = new TypedListeners();
370
+
371
+ //#endregion
372
+ //#region src/core/internal/error.ts
373
+ /** 插件名称:缺失的依赖 */
374
+ const missing = /* @__PURE__ */ new Map();
375
+ /**
376
+ * @description 插件载入错误
377
+ * @param name 插件包名
378
+ * @param file 报错的文件名称
379
+ * @param error 错误信息
380
+ */
381
+ const loaderPlugin = (name, file, error) => {
382
+ const pkg = /Cannot find package '(.+?)'/.exec(error)?.[1];
383
+ if (pkg) {
384
+ const key = `${name}.${pkg}`;
385
+ if (missing.has(key)) return;
386
+ missing.set(key, {
387
+ name,
388
+ file,
389
+ depend: pkg
390
+ });
391
+ } else {
392
+ logger.error(`载入插件错误:${logger.red(`${name}/${path.basename(file)}`)}`);
393
+ listeners.emit("error", error);
394
+ }
395
+ };
396
+ /**
397
+ * @description 定时任务执行错误
398
+ * @param name 插件包名
399
+ * @param task 任务名称
400
+ * @param error 错误信息
401
+ */
402
+ const taskStart = (name, task, error) => {
403
+ logger.error(`[定时任务][${name}][${task}] 执行错误`);
404
+ listeners.emit("error", error);
405
+ };
406
+ /**
407
+ * @description 打印插件载入错误
408
+ */
409
+ const printMissing = () => {
410
+ try {
411
+ if (!missing.size) return;
412
+ const msg = ["\n-----依赖缺失----"];
413
+ for (const [, { name, file, depend }] of missing) msg.push(`[${name}][${path.basename(file)}] 缺少依赖:${logger.red(depend)}`);
414
+ msg.push("-------------------");
415
+ const one = missing.values().next().value;
416
+ msg.push(...[
417
+ "温馨提示:",
418
+ `1. 如果是新安装的插件,请尝试执行 ${logger.red("pnpm install -P")} 自动安装依赖`,
419
+ `2. 如果执行第一步无效,请尝试执行 ${logger.red("pnpm imstall 依赖名称 -w")} 手动安装依赖`,
420
+ `举例: ${logger.red(`pnpm add ${one.depend} -w`)}`,
421
+ logger.yellow("对于手动安装的依赖,如果对应插件未在使用,请进行及时卸载: pnpm rm 依赖名称")
422
+ ]);
423
+ msg.push("-------------------");
424
+ logger.error(msg.join("\n"));
425
+ } finally {
426
+ missing.clear();
427
+ }
428
+ };
429
+ const errorHandler = {
430
+ /** 插件载入错误 */
431
+ loaderPlugin,
432
+ /** 定时任务执行错误 */
433
+ taskStart,
434
+ /** 打印插件载入错误 */
435
+ printMissing
436
+ };
437
+
438
+ //#endregion
439
+ //#region src/core/internal/status_listener.ts
440
+ var StatusHelper = class {
441
+ psCpuUsage = process.cpuUsage();
442
+ psCurrentTime = process.hrtime();
443
+ cpuTimes = os.cpus().map((cpu) => cpu.times);
444
+ replaceNaN(value) {
445
+ return isNaN(value) ? 0 : value;
446
+ }
447
+ sysCpuInfo() {
448
+ const currentTimes = os.cpus().map((cpu) => cpu.times);
449
+ const { total, active } = currentTimes.map((times, index) => {
450
+ const prevTimes = this.cpuTimes[index];
451
+ const totalCurrent = times.user + times.nice + times.sys + times.idle + times.irq;
452
+ const totalPrev = prevTimes.user + prevTimes.nice + prevTimes.sys + prevTimes.idle + prevTimes.irq;
453
+ const activeCurrent = totalCurrent - times.idle;
454
+ const activePrev = totalPrev - prevTimes.idle;
455
+ return {
456
+ total: totalCurrent - totalPrev,
457
+ active: activeCurrent - activePrev
458
+ };
459
+ }).reduce((acc, cur) => ({
460
+ total: acc.total + cur.total,
461
+ active: acc.active + cur.active
462
+ }), {
463
+ total: 0,
464
+ active: 0
465
+ });
466
+ this.cpuTimes = currentTimes;
467
+ return {
468
+ usage: this.replaceNaN(active / total * 100).toFixed(2),
469
+ model: os.cpus()[0].model,
470
+ speed: os.cpus()[0].speed,
471
+ core: os.cpus().length
472
+ };
473
+ }
474
+ sysMemoryUsage() {
475
+ const { total, free } = {
476
+ total: os.totalmem(),
477
+ free: os.freemem()
478
+ };
479
+ return ((total - free) / 1024 / 1024).toFixed(2);
480
+ }
481
+ karinUsage() {
482
+ const mem = process.memoryUsage();
483
+ const numCpus = os.cpus().length;
484
+ const usageDiff = process.cpuUsage(this.psCpuUsage);
485
+ const endTime = process.hrtime(this.psCurrentTime);
486
+ this.psCpuUsage = process.cpuUsage();
487
+ this.psCurrentTime = process.hrtime();
488
+ const normPercent = (usageDiff.user + usageDiff.system) / 1e3 / (endTime[0] * 1e3 + endTime[1] / 1e6) / numCpus * 100;
489
+ return {
490
+ cpu: this.replaceNaN(normPercent).toFixed(2),
491
+ memory: ((mem.heapTotal + mem.external + mem.arrayBuffers) / 1024 / 1024).toFixed(2)
492
+ };
493
+ }
494
+ /**
495
+ * 获取系统状态信息
496
+ */
497
+ systemStatus() {
498
+ const karinUsage = this.karinUsage();
499
+ const sysCpuInfo = this.sysCpuInfo();
500
+ const memUsage = process.memoryUsage();
501
+ let userInfo;
502
+ try {
503
+ userInfo = os.userInfo();
504
+ } catch (e) {
505
+ userInfo = void 0;
506
+ }
507
+ let loadavg;
508
+ try {
509
+ loadavg = os.loadavg();
510
+ } catch (e) {
511
+ loadavg = void 0;
512
+ }
513
+ return {
514
+ cpu: {
515
+ core: sysCpuInfo.core,
516
+ model: sysCpuInfo.model,
517
+ speed: (sysCpuInfo.speed / 1e3).toFixed(2),
518
+ usage: {
519
+ system: sysCpuInfo.usage,
520
+ karin: karinUsage.cpu
521
+ }
522
+ },
523
+ memory: {
524
+ total: (os.totalmem() / 1024 / 1024).toFixed(2),
525
+ usage: {
526
+ system: this.sysMemoryUsage(),
527
+ karin: karinUsage.memory
528
+ },
529
+ details: {
530
+ rss: (memUsage.rss / 1024 / 1024).toFixed(2),
531
+ heapTotal: (memUsage.heapTotal / 1024 / 1024).toFixed(2),
532
+ heapUsed: (memUsage.heapUsed / 1024 / 1024).toFixed(2),
533
+ external: (memUsage.external / 1024 / 1024).toFixed(2),
534
+ arrayBuffers: (memUsage.arrayBuffers / 1024 / 1024).toFixed(2)
535
+ }
536
+ },
537
+ system: {
538
+ arch: `${os.platform()} ${os.arch()}`,
539
+ hostname: os.hostname(),
540
+ osName: os.type(),
541
+ osVersion: os.release(),
542
+ platform: os.platform(),
543
+ uptime: os.uptime(),
544
+ loadavg,
545
+ tmpdir: os.tmpdir(),
546
+ homedir: os.homedir()
547
+ },
548
+ process: {
549
+ nodeVersion: process.version,
550
+ pid: process.pid,
551
+ uptime: process.uptime(),
552
+ execPath: process.execPath,
553
+ argv: process.argv,
554
+ env: {
555
+ nodeEnv: process.env.NODE_ENV,
556
+ timezone: process.env.TZ
557
+ },
558
+ user: userInfo ? {
559
+ username: userInfo.username,
560
+ homedir: userInfo.homedir,
561
+ shell: userInfo.shell
562
+ } : void 0
563
+ },
564
+ network: { interfaces: os.networkInterfaces() }
565
+ };
566
+ }
567
+ };
568
+ var StatusHelperSubscription = class extends EventEmitter {
569
+ statusHelper;
570
+ interval = null;
571
+ constructor(time = 3e3) {
572
+ super();
573
+ this.statusHelper = new StatusHelper();
574
+ this.on("newListener", (event) => {
575
+ if (event === "statusUpdate" && this.listenerCount("statusUpdate") === 0) this.startInterval(time);
576
+ });
577
+ this.on("removeListener", (event) => {
578
+ if (event === "statusUpdate" && this.listenerCount("statusUpdate") === 0) this.stopInterval();
579
+ });
580
+ }
581
+ startInterval(time) {
582
+ this.interval ??= setInterval(() => {
583
+ const status = this.statusHelper.systemStatus();
584
+ this.emit("statusUpdate", status);
585
+ }, time);
586
+ }
587
+ stopInterval() {
588
+ if (this.interval) {
589
+ clearInterval(this.interval);
590
+ this.interval = null;
591
+ }
592
+ }
593
+ };
594
+ const statusListener = new StatusHelperSubscription();
595
+
596
+ //#endregion
597
+ export { filesByExt as C, isSubPath as D, isPathEqual as E, splitPath as O, cache as S, getRelPath as T, WS_CONNECTION_SANDBOX as _, BOT_DISCONNECT as a, key_exports as b, RECV_MSG as c, WS_CLOSE_ONEBOT as d, WS_CLOSE_PUPPETEER as f, WS_CONNECTION_PUPPETEER as g, WS_CONNECTION_ONEBOT as h, BOT_CONNECT as i, urlToPath as k, SEND_MSG as l, WS_CONNECTION as m, errorHandler as n, EVENT_COUNT as o, WS_CLOSE_SANDBOX as p, listeners as r, FILE_CHANGE as s, statusListener as t, WS_CLOSE as u, WS_CONNECTION_TERMINAL as v, formatPath as w, isPublic as x, WS_SNAPKA as y };