node-karin 0.11.3 → 0.11.5

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/lib/cli/karin.js CHANGED
@@ -175,14 +175,12 @@ class KarinCli {
175
175
  async update () {
176
176
  /** 屏蔽的依赖包列表 */
177
177
  const pkgdependencies = [
178
- '@grpc/grpc-js',
179
- '@grpc/proto-loader',
180
178
  'art-template',
181
179
  'axios',
182
180
  'chalk',
183
181
  'chokidar',
182
+ 'commander',
184
183
  'express',
185
- 'kritor-proto',
186
184
  'level',
187
185
  'lodash',
188
186
  'log4js',
@@ -192,38 +190,23 @@ class KarinCli {
192
190
  'ws',
193
191
  'yaml',
194
192
  ]
195
- let cmd = ''
196
193
  const list = Object.keys(this.pkg(false).dependencies).filter(key => !pkgdependencies.includes(key))
197
194
  /** 获取包管理器 */
198
195
  const pkg = new KarinCfgInit().getRegistry()
199
- switch (pkg) {
200
- case 'pnpm': {
201
- cmd = 'pnpm update'
202
- break
203
- }
204
- case 'yarn': {
205
- cmd = 'yarn upgrade'
206
- break
207
- }
208
- case 'npm': {
209
- cmd = 'npm update'
210
- break
211
- }
212
- case 'cnpm': {
213
- cmd = 'cnpm update'
214
- break
215
- }
216
- }
196
+ const cmd = pkg === 'yarn' ? 'yarn upgrade' : `${pkg} update`
217
197
  /** 异步并发更新依赖 */
218
198
  await Promise.all(list.map(async (item) => {
219
199
  try {
220
- const res = await this.exec(`${cmd} ${item}@latest`)
221
- /** 已经是最新 */
222
- if (res.includes('is up to date')) {
200
+ /** 检查是否已经是最新版本 */
201
+ const local = await this.getLocalVersion(item, pkg)
202
+ const remote = await this.getRemoteVersion(item, pkg)
203
+ if (local === remote) {
223
204
  console.log(`[依赖更新] ${item} 已经是最新~`)
224
- } else {
225
- console.log(`[依赖更新] ${item} 更新完成~`)
205
+ return
226
206
  }
207
+ console.log(`[依赖更新] ${item} 当前版本: ${local} 最新版本: ${remote}`)
208
+ await this.exec(`${cmd} ${item}@latest`)
209
+ console.log(`[依赖更新] ${item} 更新完成~`)
227
210
  } catch (error) {
228
211
  console.error(`[依赖更新] ${item} 更新失败:`)
229
212
  console.error(`error.stack: ${error.stack}`)
@@ -233,6 +216,43 @@ class KarinCli {
233
216
  console.log('所有依赖已更新完成~')
234
217
  }
235
218
 
219
+ /**
220
+ * 获取指定包的本地版本
221
+ * @param name - 包名
222
+ * @param pkg - 包管理器
223
+ * @returns - 版本号
224
+ */
225
+ async getLocalVersion (name, pkg) {
226
+ const cmd = pkg === 'yarn' ? `yarn list --pattern ${name}` : `${pkg} list ${name} --depth=0`
227
+ const text = await this.exec(cmd)
228
+ /** pnpm特殊处理 */
229
+ if (pkg === 'pnpm') {
230
+ const reg = new RegExp(`${name}\\s+([\\d.]+)`, 'gm')
231
+ const res = reg.exec(text)
232
+ return res?.[1] || '0.0.0'
233
+ }
234
+ const reg = new RegExp(`${name}@(\\d+\\.\\d+\\.\\d+)`, 'gm')
235
+ const res = reg.exec(text)
236
+ return res?.[1] || '0.0.0'
237
+ }
238
+
239
+ /**
240
+ * 获取指定包的最新版本
241
+ * @param name - 包名
242
+ * @param pkg - 包管理器
243
+ */
244
+ async getRemoteVersion (name, pkg) {
245
+ const cmd = `${pkg} info ${name} version`
246
+ const text = await this.exec(cmd)
247
+ /** yarn特殊处理 */
248
+ if (pkg === 'yarn') {
249
+ const lines = text.split('\n').map(line => line.trim())
250
+ const ver = lines.find(line => /^\d+\.\d+\.\d+$/.test(line))
251
+ return ver || ''
252
+ }
253
+ return text.trim()
254
+ }
255
+
236
256
  /**
237
257
  * 封装exec
238
258
  * @param cmd - 命令
@@ -240,7 +260,7 @@ class KarinCli {
240
260
  exec (cmd) {
241
261
  return new Promise((resolve, reject) => {
242
262
  execCmd(cmd, (error, stdout, stderr) => {
243
- if (stdout) { return resolve(stdout) }
263
+ if (stdout) { return resolve(stdout.trim()) }
244
264
  if (error) { return reject(error) }
245
265
  return reject(stderr)
246
266
  })
@@ -154,7 +154,7 @@ export class KarinCfgInit {
154
154
  console.log('检测到已安装pnpm,开始安装依赖...');
155
155
  }
156
156
  /** 安装依赖 */
157
- if (!(await this.shell(`${type} -P --force`))) {
157
+ if (!(await this.shell(`${type} install -P --force`))) {
158
158
  console.log('安装依赖失败,请手动安装依赖!');
159
159
  console.log(`可尝试手动执行 【 ${type} install -P 】 安装依赖~`);
160
160
  console.log('如中国大陆用户安装失败,请尝试执行换源 【 npm config set registry https://registry.npmmirror.com 】后再安装依赖~');
@@ -1,6 +1,9 @@
1
1
  import { Contact, KarinElement, KarinMessage, KarinRenderType, PermissionType, RenderResult, KarinNoticeType, KarinRequestType, KarinMessageType, AllMessageSubType, CommandInfo, TaskInfo, HandlerInfo, AcceptInfo, UseInfo, AllNoticeSubType, AllRequestSubType } from '../../types/index.js';
2
2
  type FncFunction = (e: KarinMessage) => Promise<boolean>;
3
3
  type FncElement = string | KarinElement | Array<KarinElement>;
4
+ type UseReceive = (e: KarinMessageType, next: Function, exit: Function) => Promise<void>;
5
+ type UseReply = (e: KarinMessageType, element: KarinElement[], next: Function, exit: Function) => Promise<void>;
6
+ type UseRecord = (uid: string, contact: Contact, elements: KarinElement[], next: Function, exit: Function) => Promise<void>;
4
7
  /**
5
8
  * 中间件类型
6
9
  */
@@ -156,9 +159,9 @@ export declare class Karin {
156
159
  * @param fn - 实现函数
157
160
  */
158
161
  accept(event: AllNoticeSubType | AllRequestSubType, fn: (e: KarinNoticeType | KarinRequestType) => Promise<boolean>, options?: Options): AcceptInfo;
159
- use(type: `${MiddlewareType.ReceiveMsg}`, fn: (e: KarinMessageType, next: Function) => Promise<void>, options: Omit<Options, 'log'>): UseInfo;
160
- use(type: `${MiddlewareType.ReplyMsg}`, fn: (e: KarinMessageType, element: KarinElement[], next: Function) => Promise<void>, options: Omit<Options, 'log'>): UseInfo;
161
- use(type: `${MiddlewareType.SendMsg}`, fn: (uid: string, contact: Contact, elements: KarinElement[]) => Promise<void>, options: Omit<Options, 'log'>): UseInfo;
162
+ use(type: `${MiddlewareType.ReceiveMsg}`, fn: UseReceive, options?: Omit<Options, 'log'>): UseInfo;
163
+ use(type: `${MiddlewareType.ReplyMsg}`, fn: UseReply, options?: Omit<Options, 'log'>): UseInfo;
164
+ use(type: `${MiddlewareType.SendMsg}`, fn: UseRecord, options?: Omit<Options, 'log'>): UseInfo;
162
165
  /**
163
166
  * - 启动
164
167
  */
@@ -176,12 +176,21 @@ export class Listeners extends EventEmitter {
176
176
  * @param options.retry_count - 重试次数
177
177
  */
178
178
  async sendMsg(uid, contact, elements, options = { recallMsg: 0, retry_count: 1 }) {
179
+ /** 结果 */
180
+ let result = {};
179
181
  /** 先调用中间件 */
180
182
  for (const info of pluginLoader.use.sendMsg) {
181
183
  try {
182
184
  let next = false;
185
+ let exit = false;
183
186
  const nextFn = () => { next = true; };
184
- await info.fn(uid, contact, elements, nextFn);
187
+ const exitFn = () => { exit = true; };
188
+ await info.fn(uid, contact, elements, nextFn, exitFn);
189
+ if (exit) {
190
+ const plugin = pluginLoader.plugin.get(info.key);
191
+ logger.debug(`[消息中间件][${plugin.plugin}][${plugin.file}] 主动操作退出`);
192
+ return result;
193
+ }
185
194
  if (!next)
186
195
  break;
187
196
  }
@@ -196,8 +205,6 @@ export class Listeners extends EventEmitter {
196
205
  const { recallMsg, retry_count } = options;
197
206
  /** 标准化 */
198
207
  const NewElements = common.makeMessage(elements);
199
- /** 结果 */
200
- let result = {};
201
208
  const reply_log = common.makeMessageLog(NewElements);
202
209
  const self_id = bot.account.uid || bot.account.uin;
203
210
  if (contact.scene === 'group') {
@@ -55,7 +55,7 @@ declare class PluginLoader {
55
55
  [key: string]: PluginHandlerInfoType[];
56
56
  };
57
57
  /** plugin基本信息 */
58
- plugin: PluginInfoType;
58
+ plugin: Map<number, PluginInfoType>;
59
59
  /** task定时任务信息 */
60
60
  task: PluginTaskInfoType[];
61
61
  /** 中间件 */
@@ -49,7 +49,7 @@ class PluginLoader {
49
49
  this.button = [];
50
50
  this.command = [];
51
51
  this.handler = {};
52
- this.plugin = {};
52
+ this.plugin = new Map();
53
53
  this.task = [];
54
54
  this.use = {
55
55
  recvMsg: [],
@@ -312,7 +312,7 @@ class PluginLoader {
312
312
  try {
313
313
  const index = ++this.index;
314
314
  /** 缓存基本信息 */
315
- this.plugin[index] = { type, plugin, path: _path, file };
315
+ this.plugin.set(index, { type, plugin, path: _path, file });
316
316
  const list = [];
317
317
  let rootPath = 'file://' + path.join(process.cwd(), type === 'npm' ? 'node_modules' : 'plugins', plugin, _path, file);
318
318
  if (isOrderBy)
@@ -422,7 +422,7 @@ class PluginLoader {
422
422
  name: info.name,
423
423
  event: info.event,
424
424
  fn: info.fn,
425
- key: index + '',
425
+ key: index,
426
426
  log: info.log,
427
427
  rank: info.rank,
428
428
  });
@@ -433,7 +433,7 @@ class PluginLoader {
433
433
  name: info.name,
434
434
  reg: info.reg,
435
435
  fn: info.fn,
436
- key: index + '',
436
+ key: index,
437
437
  rank: info.rank,
438
438
  });
439
439
  return true;
@@ -444,7 +444,7 @@ class PluginLoader {
444
444
  this.handler[info.key].push({
445
445
  name: info.name,
446
446
  fn: info.fn,
447
- key: index + '',
447
+ key: index,
448
448
  rank: info.rank,
449
449
  });
450
450
  return true;
@@ -456,7 +456,7 @@ class PluginLoader {
456
456
  event: info.event,
457
457
  fn: info.fn,
458
458
  fnname: info.fnname,
459
- key: index + '',
459
+ key: index,
460
460
  log: info.log,
461
461
  perm: info.perm,
462
462
  rank: info.rank,
@@ -470,7 +470,7 @@ class PluginLoader {
470
470
  name: info.name,
471
471
  cron: info.cron,
472
472
  fn: info.fn,
473
- key: index + '',
473
+ key: index,
474
474
  taskname: info.fnname,
475
475
  data: App,
476
476
  log: info.log,
@@ -498,7 +498,7 @@ class PluginLoader {
498
498
  this.use[info.key].push({
499
499
  name: info.name,
500
500
  fn: info.fn,
501
- key: index + '',
501
+ key: index,
502
502
  rank: info.rank,
503
503
  });
504
504
  return true;
@@ -530,11 +530,10 @@ class PluginLoader {
530
530
  * 卸载插件
531
531
  */
532
532
  uninstallApp(plugin, _path, file) {
533
- Object.keys(this.plugin).forEach(key => {
534
- const info = this.plugin[key];
533
+ this.plugin.forEach((info, key) => {
535
534
  if (info.plugin === plugin && info.path === _path && info.file === file) {
536
535
  /** 删除缓存 */
537
- delete this.plugin[key];
536
+ this.plugin.delete(key);
538
537
  this.accept = this.accept.filter(val => val.key !== key);
539
538
  this.button = this.button.filter(val => val.key !== key);
540
539
  this.command = this.command.filter(val => val.key !== key);
@@ -8,13 +8,13 @@ export class EventBaseHandler {
8
8
  /**
9
9
  * - 是否打印群消息日志
10
10
  */
11
- GroupMsgPrint = true;
11
+ GroupMsgPrint;
12
12
  /**
13
13
  * 处理事件,加入自定义字段
14
14
  */
15
15
  constructor(e) {
16
16
  this.e = e;
17
- this.GroupMsgPrint = false;
17
+ this.GroupMsgPrint = true;
18
18
  /** 加入e.bot */
19
19
  !this.e.bot && Object.defineProperty(this.e, 'bot', { value: listener.getBot(this.e.self_id) });
20
20
  if (this.e.group_id)
@@ -132,13 +132,27 @@ export class EventBaseHandler {
132
132
  * @param options 回复选项
133
133
  */
134
134
  this.e.reply = async (elements = '', options = { reply: false, recallMsg: 0, at: false, retry_count: 1 }) => {
135
+ const request = {
136
+ message_id: '',
137
+ message_time: 0,
138
+ raw_data: undefined,
139
+ };
135
140
  const message = common.makeMessage(elements);
136
141
  /** 先调用中间件 */
137
142
  for (const info of pluginLoader.use.replyMsg) {
138
143
  try {
139
144
  let next = false;
145
+ let exit = false;
140
146
  const nextFn = () => { next = true; };
141
- await info.fn(this.e, message, nextFn);
147
+ const exitFn = () => { exit = true; };
148
+ await info.fn(this.e, message, nextFn, exitFn);
149
+ if (exit) {
150
+ const plugin = pluginLoader.plugin.get(info.key);
151
+ logger.debug(`[消息中间件][${plugin.plugin}][${plugin.file}] 主动操作退出`);
152
+ return request;
153
+ }
154
+ if (!next)
155
+ break;
142
156
  if (!next)
143
157
  break;
144
158
  }
@@ -162,11 +176,6 @@ export class EventBaseHandler {
162
176
  else {
163
177
  this.e.self_id !== 'input' && logger.bot('info', this.e.self_id, `${logger.green(`Send private ${this.e.user_id}: `)}${ReplyLog}`);
164
178
  }
165
- const request = {
166
- message_id: '',
167
- message_time: 0,
168
- raw_data: undefined,
169
- };
170
179
  try {
171
180
  listener.emit('karin:count:send', 1);
172
181
  /** 取结果 */
@@ -199,8 +199,15 @@ export class MessageHandler extends EventBaseHandler {
199
199
  for (const info of pluginLoader.use.recvMsg) {
200
200
  try {
201
201
  let next = false;
202
+ let exit = false;
202
203
  const nextFn = () => { next = true; };
203
- await info.fn(this.e, nextFn);
204
+ const exitFn = () => { exit = true; };
205
+ await info.fn(this.e, nextFn, exitFn);
206
+ if (exit) {
207
+ const plugin = pluginLoader.plugin.get(info.key);
208
+ logger.debug(`[消息中间件][${plugin.plugin}][${plugin.file}] 主动操作退出`);
209
+ return;
210
+ }
204
211
  if (!next)
205
212
  break;
206
213
  }
@@ -248,7 +255,7 @@ export class MessageHandler extends EventBaseHandler {
248
255
  res = await info.fn.call(app, this.e);
249
256
  }
250
257
  this.GroupMsgPrint && info.log(this.e.self_id, `${logFnc} ${lodash.truncate(this.e.msg, { length: 80 })} 处理完成 ${logger.green(Date.now() - start + 'ms')}`);
251
- if (res !== false)
258
+ if (res === false)
252
259
  continue;
253
260
  return;
254
261
  }
@@ -27,6 +27,7 @@ export class NoticeHandler extends EventBaseHandler {
27
27
  this.deal();
28
28
  }
29
29
  init() {
30
+ this.raw_message();
30
31
  /** 主人 */
31
32
  if (config.master.includes(String(this.e.user_id))) {
32
33
  this.e.isMaster = true;
@@ -55,7 +56,6 @@ export class NoticeHandler extends EventBaseHandler {
55
56
  else {
56
57
  logger.bot('info', this.e.self_id, `未知来源通知事件:${JSON.stringify(this.e)}`);
57
58
  }
58
- this.raw_message();
59
59
  this.reply();
60
60
  }
61
61
  /**
@@ -27,6 +27,7 @@ export class RequestHandler extends EventBaseHandler {
27
27
  this.deal();
28
28
  }
29
29
  init() {
30
+ this.raw_message();
30
31
  /** 主人 */
31
32
  if (config.master.includes(String(this.e.user_id))) {
32
33
  this.e.isMaster = true;
@@ -50,7 +51,6 @@ export class RequestHandler extends EventBaseHandler {
50
51
  else {
51
52
  logger.bot('info', this.e.self_id, `未知来源请求事件:${JSON.stringify(this.e)}`);
52
53
  }
53
- this.raw_message();
54
54
  this.reply();
55
55
  }
56
56
  /**
@@ -194,7 +194,7 @@ export const review = new (class Handler {
194
194
  /** 同时启用 */
195
195
  if (this.App.GroupConfig.enable && this.App.GroupConfig.disable) {
196
196
  this.PluginEnable = (app, config) => {
197
- const plugin = pluginLoader.plugin[app.key];
197
+ const plugin = pluginLoader.plugin.get(app.key);
198
198
  /** 白名单不为空 */
199
199
  if (Array.isArray(config.enable) && config.enable.length) {
200
200
  /** 插件包是否处于功能白名单 */
@@ -229,7 +229,7 @@ export const review = new (class Handler {
229
229
  /** 白名单启用 */
230
230
  if (this.App.GroupConfig.enable) {
231
231
  this.PluginEnable = (app, config) => {
232
- const plugin = pluginLoader.plugin[app.key];
232
+ const plugin = pluginLoader.plugin.get(app.key);
233
233
  if (Array.isArray(config.enable) && config.enable.length) {
234
234
  for (const key of config.enable) {
235
235
  if (key.plugin === plugin.plugin)
@@ -247,7 +247,7 @@ export const review = new (class Handler {
247
247
  /** 黑名单启用 */
248
248
  if (this.App.GroupConfig.disable) {
249
249
  this.PluginEnable = (app, config) => {
250
- const plugin = pluginLoader.plugin[app.key];
250
+ const plugin = pluginLoader.plugin.get(app.key);
251
251
  if (Array.isArray(config.disable) && config.disable.length) {
252
252
  for (const key of config.disable) {
253
253
  if (key.plugin === plugin.plugin) {
@@ -40,23 +40,21 @@ export declare const enum MethodType {
40
40
  * plugin基本信息
41
41
  */
42
42
  export interface PluginInfoType {
43
- [key: string]: {
44
- /** 插件包类型 */
45
- type: `${AppsType}`;
46
- /** 插件包名称 例: `karin-plugin-example` `@karinjs/adapter-qqbot` */
47
- plugin: string;
48
- /** 插件路径 在type为js下,path为空 */
49
- path: string;
50
- /** 插件文件名称 index.js index.ts */
51
- file: string;
52
- };
43
+ /** 插件包类型 */
44
+ type: `${AppsType}`;
45
+ /** 插件包名称 例: `karin-plugin-example` `@karinjs/adapter-qqbot` */
46
+ plugin: string;
47
+ /** 插件路径 在type为js下,path为空 */
48
+ path: string;
49
+ /** 插件文件名称 index.js index.ts */
50
+ file: string;
53
51
  }
54
52
  /**
55
53
  * Command规则集信息
56
54
  */
57
55
  export interface PluginCommandInfoType {
58
56
  /** 插件基本信息的映射key */
59
- key: string;
57
+ key: number;
60
58
  /** 插件包名称 */
61
59
  name: string;
62
60
  /** 插件正则 */
@@ -83,7 +81,7 @@ export interface PluginCommandInfoType {
83
81
  */
84
82
  export interface PluginAcceptInfoType {
85
83
  /** 插件基本信息的映射key */
86
- key: string;
84
+ key: number;
87
85
  /** 插件包名称 */
88
86
  name: string;
89
87
  /** 插件执行方法 */
@@ -100,7 +98,7 @@ export interface PluginAcceptInfoType {
100
98
  */
101
99
  export interface PluginTaskInfoType {
102
100
  /** 插件基本信息的映射key */
103
- key: string;
101
+ key: number;
104
102
  /** 插件包名称 */
105
103
  name: string;
106
104
  /** 任务名称 */
@@ -121,7 +119,7 @@ export interface PluginTaskInfoType {
121
119
  */
122
120
  export interface PluginButtonInfoType {
123
121
  /** 插件基本信息的映射key */
124
- key: string;
122
+ key: number;
125
123
  /** 插件包名称 */
126
124
  name: string;
127
125
  /** 插件正则 */
@@ -136,7 +134,7 @@ export interface PluginButtonInfoType {
136
134
  */
137
135
  export interface PluginHandlerInfoType {
138
136
  /** 插件基本信息的映射key */
139
- key: string;
137
+ key: number;
140
138
  /** 插件包名称 */
141
139
  name: string;
142
140
  /** handler的处理方法 */
@@ -151,22 +149,24 @@ export interface PluginMiddlewareInfoType {
151
149
  /** 初始化消息前 */
152
150
  recvMsg: Array<{
153
151
  /** 插件基本信息的映射key */
154
- key: string;
152
+ key: number;
155
153
  /** 插件包名称 */
156
154
  name: string;
157
155
  /** 插件执行方法 */
158
156
  fn: (
159
157
  /** 消息事件方法 */
160
158
  e: KarinMessageType,
161
- /** 是否继续执行插件 */
162
- next: Function) => Promise<boolean>;
159
+ /** 是否继续执行下一个中间件 */
160
+ next: Function,
161
+ /** 是否退出此条消息 不再执行匹配插件 */
162
+ exit: Function) => Promise<boolean>;
163
163
  /** 优先级 */
164
164
  rank: number;
165
165
  }>;
166
166
  /** 回复消息前 */
167
167
  replyMsg: Array<{
168
168
  /** 插件基本信息的映射key */
169
- key: string;
169
+ key: number;
170
170
  /** 插件包名称 */
171
171
  name: string;
172
172
  /** 插件执行方法 */
@@ -175,15 +175,17 @@ export interface PluginMiddlewareInfoType {
175
175
  e: KarinMessageType,
176
176
  /** 回复的消息体 */
177
177
  element: KarinElement[],
178
- /** 是否继续执行插件 */
179
- next: Function) => Promise<boolean>;
178
+ /** 是否继续执行下一个中间件 */
179
+ next: Function,
180
+ /** 是否不发送此条消息 */
181
+ exit: Function) => Promise<boolean>;
180
182
  /** 优先级 */
181
183
  rank: number;
182
184
  }>;
183
185
  /** 发送主动消息前 */
184
186
  sendMsg: Array<{
185
187
  /** 插件基本信息的映射key */
186
- key: string;
188
+ key: number;
187
189
  /** 插件包名称 */
188
190
  name: string;
189
191
  /** 插件执行方法 */
@@ -194,8 +196,10 @@ export interface PluginMiddlewareInfoType {
194
196
  contact: Contact,
195
197
  /** 发送的消息体 */
196
198
  element: KarinElement[],
197
- /** 是否继续执行插件 */
198
- next: Function) => Promise<boolean>;
199
+ /** 是否继续执行下一个中间件 */
200
+ next: Function,
201
+ /** 是否不发送此条消息 */
202
+ exit: Function) => Promise<boolean>;
199
203
  /** 优先级 */
200
204
  rank: number;
201
205
  }>;
@@ -85,6 +85,16 @@ declare class Common {
85
85
  * - 写入yaml文件
86
86
  */
87
87
  writeYaml(file: string, data: any): boolean;
88
+ /**
89
+ * 输入包名 返回包根目录的绝对路径 仅简单查找
90
+ * @param name - 包名
91
+ * @param _path - 导入包的路径 此项适用于在插件中读取插件的依赖包
92
+ * @returns - 包根目录的绝对路径
93
+ * @example
94
+ * common.pkgroot('axios')
95
+ * common.pkgroot('axios', import.meta.url)
96
+ */
97
+ pkgroot(name: string, _path?: string): string;
88
98
  /**
89
99
  * 根据文件后缀名从指定路径下读取符合要求的文件
90
100
  * @param path - 路径
@@ -5,6 +5,7 @@ import axios from 'axios';
5
5
  import lodash from 'lodash';
6
6
  import { promisify } from 'util';
7
7
  import { fileURLToPath } from 'url';
8
+ import { createRequire } from 'module';
8
9
  import { pipeline, Readable } from 'stream';
9
10
  import { logger, segment, YamlEditor } from '../../utils/index.js';
10
11
  /**
@@ -190,6 +191,32 @@ class Common {
190
191
  return false;
191
192
  }
192
193
  }
194
+ /**
195
+ * 输入包名 返回包根目录的绝对路径 仅简单查找
196
+ * @param name - 包名
197
+ * @param _path - 导入包的路径 此项适用于在插件中读取插件的依赖包
198
+ * @returns - 包根目录的绝对路径
199
+ * @example
200
+ * common.pkgroot('axios')
201
+ * common.pkgroot('axios', import.meta.url)
202
+ */
203
+ pkgroot(name, _path) {
204
+ const require = createRequire(_path || import.meta.url);
205
+ let dir = require.resolve(name);
206
+ if (fs.existsSync(path.join(dir, 'package.json')))
207
+ return path.resolve(dir);
208
+ /** 递归查找 如果跳过了node_modules 则返回null */
209
+ while (true) {
210
+ /** 向上 */
211
+ dir = path.dirname(dir);
212
+ if (fs.existsSync(path.join(dir, 'package.json')))
213
+ return path.resolve(dir);
214
+ /** 加个处理 防止无线递归 */
215
+ if (dir === path.dirname(dir)) {
216
+ throw new Error(`[common] 未找到包${name}的根目录`);
217
+ }
218
+ }
219
+ }
193
220
  /**
194
221
  * 根据文件后缀名从指定路径下读取符合要求的文件
195
222
  * @param path - 路径
@@ -204,7 +231,6 @@ class Common {
204
231
  const list = [];
205
232
  if (!Array.isArray(ext))
206
233
  ext = [ext];
207
- // 排除文件夹 和不符合后缀名的文件
208
234
  files.forEach(v => {
209
235
  if (v.isDirectory())
210
236
  return;
@@ -380,7 +406,7 @@ class Common {
380
406
  */
381
407
  async getNpmPlugins(showDetails) {
382
408
  /** 屏蔽的依赖包列表 */
383
- const exclude = ['art-template', 'axios', 'chalk', 'chokidar', 'express', 'level', 'lodash', 'log4js', 'moment', 'node-karin', 'node-schedule', 'redis', 'ws', 'yaml'];
409
+ const exclude = ['art-template', 'axios', 'chalk', 'chokidar', 'commander', 'express', 'level', 'lodash', 'log4js', 'moment', 'node-karin', 'node-schedule', 'redis', 'ws', 'yaml'];
384
410
  const pkg = this.readJson('./package.json');
385
411
  const dependencies = Object.keys(pkg.dependencies).filter((name) => !exclude.includes(name));
386
412
  if (!showDetails) {
@@ -12,7 +12,7 @@ export const handler = new (class EventHandler {
12
12
  async call(key, args) {
13
13
  let res;
14
14
  for (const info of loader.handler[key] || []) {
15
- const plugin = loader.plugin[info.key];
15
+ const plugin = loader.plugin.get(info.key);
16
16
  try {
17
17
  let done = true;
18
18
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-karin",
3
- "version": "0.11.3",
3
+ "version": "0.11.5",
4
4
  "private": false,
5
5
  "description": "基于 Kritor 进行开发的nodejs机器人框架",
6
6
  "homepage": "https://github.com/KarinJS/Karin",
@@ -140,7 +140,7 @@
140
140
  },
141
141
  "dependencies": {
142
142
  "art-template": "4.13.2",
143
- "axios": "1.7.2",
143
+ "axios": "1.7.3",
144
144
  "chalk": "5.3.0",
145
145
  "chokidar": "3.6.0",
146
146
  "commander": "^12.1.0",
@@ -150,9 +150,9 @@
150
150
  "log4js": "6.9.1",
151
151
  "moment": "2.30.1",
152
152
  "node-schedule": "2.1.1",
153
- "redis": "4.6.15",
153
+ "redis": "4.7.0",
154
154
  "ws": "8.18.0",
155
- "yaml": "2.4.5"
155
+ "yaml": "2.5.0"
156
156
  },
157
157
  "devDependencies": {
158
158
  "@types/express": "^4.17.21",