node-karin 0.2.2 → 0.3.0

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.
@@ -1,21 +1,43 @@
1
1
  import fs from 'fs'
2
2
  import path from 'path'
3
3
  import lodash from 'lodash'
4
+ import chokidar from 'chokidar'
4
5
  import schedule from 'node-schedule'
5
6
  import { listener } from './listener.js'
6
7
  import PluginApp from './plugin.app.js'
7
- import { render } from '../renderer/index.js'
8
- import { button, common, handler, logger } from '../utils/index.js'
8
+ import { render } from '../render/index.js'
9
+ import { common, handler, logger } from '../utils/index.js'
9
10
  /**
10
11
  * 加载插件
11
12
  */
12
- export const PluginLoader = new (class PluginLoader {
13
+ export const pluginLoader = new (class PluginLoader {
13
14
  dir
14
15
  dirPath
16
+ /**
17
+ * - 插件索引ID
18
+ */
19
+ index
20
+ /**
21
+ * - 命令插件索引列表
22
+ */
23
+ ruleIds
24
+ buttonIds
25
+ /**
26
+ * - handler
27
+ */
28
+ handlerIds
15
29
  /**
16
30
  * - 插件列表
17
31
  */
18
- Apps
32
+ FileList
33
+ /**
34
+ * - 是否ts环境
35
+ */
36
+ isTs
37
+ /**
38
+ * - 最终缓存的插件列表 通过index索引
39
+ */
40
+ PluginList
19
41
  /**
20
42
  * - 定时任务
21
43
  */
@@ -28,59 +50,40 @@ export const PluginLoader = new (class PluginLoader {
28
50
  * - 热更新列表
29
51
  */
30
52
  watchList
31
- /**
32
- * - 插件索引ID
33
- */
34
- index
35
- /**
36
- * - 命令插件索引列表
37
- */
38
- rule
39
- PluginList
40
53
  constructor () {
54
+ this.index = 0
41
55
  this.dir = './plugins'
42
56
  this.dirPath = common.urlToPath(import.meta.url)
43
- this.Apps = []
44
- this.task = []
57
+ this.isTs = process.env.karin_app_lang === 'ts'
45
58
  this.watcher = new Map()
46
- /** 热更新收集 */
47
59
  this.watchList = []
48
- this.rule = []
49
- this.index = 0
60
+ this.FileList = []
50
61
  this.PluginList = {}
62
+ this.task = []
63
+ this.ruleIds = []
64
+ this.buttonIds = []
65
+ this.handlerIds = {}
51
66
  }
52
67
 
53
68
  /**
54
69
  * 插件初始化
55
70
  */
56
71
  async load () {
57
- const files = this.getPlugins()
58
- listener.once('plugin.loader', () => {
59
- for (const v of this.watchList) {
60
- v.name ? this.watch(v.dir, v.name) : this.watchDir(v.dir)
61
- }
72
+ this.getPlugins()
73
+ listener.once('plugin.watch', () => {
74
+ for (const v of this.watchList) { v.name ? this.watch(v.dir, v.name) : this.watchDir(v.dir) }
62
75
  })
63
76
  logger.info(logger.green('-----------'))
64
77
  logger.info('加载插件中..')
65
78
  /** 载入插件 */
66
- const promises = files.map(async ({ dir, name }) => await this.createdApp(dir, name, false))
79
+ const promises = this.FileList.map(async ({ dir, name }) => await this.createdApp(dir, name, false))
67
80
  /** 等待所有插件加载完成 */
68
81
  await Promise.all(promises)
69
- const handlerKeys = Object.keys(handler.events)
70
- let handlerCount = 0
71
- handlerKeys.forEach((key) => {
72
- handlerCount += handler.events[key].length
73
- })
74
- logger.info(`[按钮][${button.Apps.length}个] 加载完成`)
75
- logger.info(`[插件][${this.Apps.length}个] 加载完成`)
76
- logger.info(`[渲染器][${render.Apps.length}个] 加载完成`)
77
- logger.info(`[定时任务][${this.task.length}个] 加载完成`)
78
- logger.info(`[Handler][Key:${handlerKeys.length}个][fnc:${handlerCount}个] 加载完成`)
79
- logger.info(logger.green('-----------'))
80
- logger.info(`Karin启动完成:耗时 ${logger.green(process.uptime().toFixed(2))} 秒...`)
81
- /** 优先级排序 */
82
- this.orderBy()
83
- listener.emit('plugin.loader')
82
+ /** 释放缓存 */
83
+ this.FileList = []
84
+ /** 优先级排序并打印插件信息 */
85
+ this.orderBy(true)
86
+ listener.emit('plugin.watch')
84
87
  return this
85
88
  }
86
89
 
@@ -88,51 +91,69 @@ export const PluginLoader = new (class PluginLoader {
88
91
  * 获取所有插件
89
92
  */
90
93
  getPlugins () {
91
- const Apps = []
92
94
  /** 获取所有插件包 */
93
95
  const plugins = common.getPlugins()
94
- const isTs = process.env.karin_app_lang === 'ts'
95
96
  for (const dir of plugins) {
96
97
  /**
97
98
  * - 插件包路径
98
99
  * - 例如: ./plugins/karin-plugin-example
99
100
  */
100
101
  const PluginPath = `${this.dir}/${dir}`
101
- // 非插件包
102
+ /**
103
+ * 一共3种模式
104
+ * 1. npm run dev 开发模式 直接加载ts,js文件,对于同时存在编译产物、源代码的情况,优先加载编译产物而不加载源代码
105
+ * 2. node . 生产模式 只加载js文件
106
+ * 3. npm run debug 调试模式 在2的基础上,对apps进行热更新
107
+ */
108
+ /** 非插件包 加载该文件夹下全部js 视语言环境加载ts */
102
109
  if (!common.isPlugin(PluginPath)) {
103
- const list = fs.readdirSync(`${this.dir}/${dir}`, {
104
- withFileTypes: true,
105
- })
110
+ this.watchList.push({ dir })
111
+ const list = fs.readdirSync(`${this.dir}/${dir}`, { withFileTypes: true })
106
112
  for (const file of list) {
107
113
  /** 忽略不符合规则的文件 */
108
- const ext = isTs ? ['.js', '.ts'] : ['.js']
114
+ const ext = this.isTs ? ['.js', '.ts'] : ['.js']
109
115
  if (!ext.includes(path.extname(file.name))) { continue }
110
- Apps.push({ dir, name: file.name })
116
+ this.FileList.push({ dir, name: file.name })
111
117
  }
118
+ continue
112
119
  }
113
- /** js环境 */
114
- if (common.exists(`${PluginPath}/index.js`)) {
115
- Apps.push({ dir, name: 'index.js' })
120
+ /** 入口文件 */
121
+ const index = this.getIndex(PluginPath, process.env.karin_app_lang)
122
+ if (index) {
123
+ this.watchList.push({ dir, name: index })
124
+ this.FileList.push({ dir, name: index })
116
125
  }
117
- const appList = ['apps', 'dist/apps']
118
- appList.forEach(app => {
119
- if (common.isDir(`${PluginPath}/${app}`)) {
120
- const result = this.getApps((`${dir}/${app}`))
121
- Apps.push(...result)
122
- }
123
- })
124
- /** ts环境 */
125
- if (isTs) {
126
- if (common.exists(`${PluginPath}/index.ts`)) {
127
- Apps.push({ dir, name: 'index.ts' })
126
+ /** ts环境 全部加载 如果存在编译产物 则不加载ts */
127
+ if (this.isTs) {
128
+ /** 编译产物 存在不加载ts */
129
+ if (common.exists(`${PluginPath}/dist/apps`)) {
130
+ this.getApps((`${dir}/dist/apps`), false)
131
+ continue
128
132
  }
129
- if (common.isDir(`${PluginPath}/src/apps`)) {
130
- const result = this.getApps((`${dir}/src/apps`), true)
131
- Apps.push(...result)
133
+ /** ts */
134
+ if (common.exists(`${PluginPath}/src/apps`)) {
135
+ this.getApps((`${dir}/src/apps`), true)
136
+ continue
132
137
  }
133
138
  }
139
+ /** js环境 */
140
+ if (common.isDir(`${PluginPath}/apps`)) { this.getApps(`${dir}/apps`, false) }
141
+ /** 这里需要判断下 不然ts环境下会重复加载 */
142
+ if (!this.isTs && common.isDir(`${PluginPath}/dist/apps`)) { this.getApps(`${dir}/dist/apps`, false) }
134
143
  }
135
- return Apps
144
+ }
145
+
146
+ /**
147
+ * 传入路径 语言环境 返回加载index.ts 还是 index.js
148
+ * @param path - 插件路径
149
+ * @param lang - 语言环境
150
+ */
151
+ getIndex (path, lang) {
152
+ const isJS = common.exists(`${path}/index.js`)
153
+ if (isJS && lang === 'js') { return 'index.js' }
154
+ const isTS = common.exists(`${path}/index.ts`)
155
+ if (isTS && lang === 'ts') { return 'index.ts' }
156
+ return false
136
157
  }
137
158
 
138
159
  /**
@@ -140,66 +161,49 @@ export const PluginLoader = new (class PluginLoader {
140
161
  * @param dir - 插件包名称
141
162
  * @param isTs - 是否获取ts插件
142
163
  */
143
- getApps (dir, isTs = false) {
144
- const info = []
164
+ getApps (dir, isTs) {
165
+ this.watchList.push({ dir })
145
166
  const ext = isTs ? ['.js', '.ts'] : ['.js']
146
167
  const list = fs.readdirSync(`${this.dir}/${dir}`, { withFileTypes: true })
147
168
  for (const file of list) {
148
- // 获取后缀
149
169
  const extname = path.extname(file.name)
150
170
  if (!ext.includes(extname)) { continue }
151
- info.push({ dir, name: file.name })
171
+ this.FileList.push({ dir, name: file.name })
152
172
  }
153
- return info
154
173
  }
155
174
 
156
175
  /**
157
- * 构建插件信息
158
- */
159
- App (
160
- /**
161
- * - 插件Class 未实例化
162
- */
163
- App,
164
- /**
165
- * - 插件实例化后的Class
166
- */
167
- Class,
168
- /**
169
- * - 插件文件信息
176
+ * 排序并打印插件加兹安信息
177
+ * @param isPrint - 是否打印
170
178
  */
171
- file) {
172
- const info = {
173
- App,
174
- /** 插件文件信息 */
175
- file,
176
- name: Class.name,
177
- desc: Class.dsc || Class.desc || Class.name,
178
- event: Class.event || 'message',
179
- priority: Class.priority ?? 5000,
180
- accept: typeof Class.accept === 'function',
181
- rule: Class.rule || [],
182
- type: typeof App === 'function' ? 'function' : 'class',
183
- task: Class.task || [],
184
- handler: Class.handler || [],
185
- button: Class.button || [],
186
- }
187
- /** 进一步处理rule */
188
- info.rule.forEach((val, index) => {
189
- info.rule[index].reg = new RegExp(val.reg)
190
- info.rule[index].log = val.log === false ? (id, log) => logger.debug('mark', id, log) : (id, log) => logger.bot('mark', id, log)
191
- })
192
- return info
193
- }
194
-
195
- /** 排序 */
196
- orderBy () {
197
- const list = []
179
+ orderBy (isPrint = false) {
180
+ let taskCount = 0
181
+ let handlerCount = 0
182
+ const rule = []
183
+ const button = []
198
184
  Object.keys(this.PluginList).forEach(key => {
199
- list.push({ key, val: this.PluginList[key].priority })
185
+ taskCount += this.PluginList[key].task.length
186
+ if (this.PluginList[key].rule.length) { rule.push({ key, val: this.PluginList[key].priority }) }
187
+ if (this.PluginList[key].button.length) { button.push({ key, val: this.PluginList[key].priority }) }
200
188
  })
201
- this.rule = lodash.orderBy(list, ['val'], ['asc']).map((v) => Number(v.key))
189
+ this.ruleIds = lodash.orderBy(rule, ['val'], ['asc']).map((v) => Number(v.key))
202
190
  logger.debug('rule排序完成...')
191
+ this.buttonIds = lodash.orderBy(button, ['val'], ['asc']).map((v) => Number(v.key))
192
+ logger.debug('button排序完成...')
193
+ if (!isPrint) { return }
194
+ const PluginListKeys = Object.keys(this.PluginList)
195
+ const handlerKeys = Object.keys(this.handlerIds)
196
+ handlerKeys.forEach((key) => {
197
+ handlerCount += this.handlerIds[key].length
198
+ })
199
+ logger.info(`[插件][${PluginListKeys.length}个] 加载完成`)
200
+ logger.info(`[渲染器][${render.Apps.length}个] 加载完成`)
201
+ logger.info(`[rule][${this.ruleIds.length}个] 加载完成`)
202
+ logger.info(`[button][${this.buttonIds.length}个] 加载完成`)
203
+ logger.info(`[定时任务][${taskCount}个] 加载完成`)
204
+ logger.info(`[Handler][Key:${handlerKeys.length}个][fnc:${handlerCount}个] 加载完成`)
205
+ logger.info(logger.green('-----------'))
206
+ logger.info(`Karin启动完成:耗时 ${logger.green(process.uptime().toFixed(2))} 秒...`)
203
207
  }
204
208
 
205
209
  /**
@@ -240,7 +244,7 @@ export const PluginLoader = new (class PluginLoader {
240
244
  accept: Class.accept && typeof Class.accept === 'function',
241
245
  })
242
246
  /** 定时任务 */
243
- lodash.forEach(Class.task, (val) => {
247
+ lodash.forEach(Class.task, val => {
244
248
  if (!val.name) { return logger.error(`[${dir}][${name}] 定时任务name错误`) }
245
249
  if (!val.cron) { return logger.error(`[${dir}][${name}] 定时任务cron错误:${Class.name}`) }
246
250
  info.task.push({
@@ -266,7 +270,7 @@ export const PluginLoader = new (class PluginLoader {
266
270
  })
267
271
  })
268
272
  /** rule */
269
- lodash.forEach(Class.rule, (val) => {
273
+ lodash.forEach(Class.rule, val => {
270
274
  if (!val.fnc) { return logger.error(`[${dir}][${name}] rule.fnc错误:${Class.name}`) }
271
275
  info.rule.push({
272
276
  reg: val.reg instanceof RegExp ? val.reg : new RegExp(val.reg),
@@ -276,6 +280,16 @@ export const PluginLoader = new (class PluginLoader {
276
280
  log: val.log === false ? (id, log) => logger.debug('mark', id, log) : (id, log) => logger.bot('mark', id, log),
277
281
  })
278
282
  })
283
+ /** button */
284
+ lodash.forEach(Class.button, val => {
285
+ if (!val.fnc) { return logger.error(`[${dir}][${name}] rule.fnc错误:${Class.name}`) }
286
+ info.button.push({
287
+ reg: val.reg instanceof RegExp ? val.reg : new RegExp(val.reg),
288
+ fnc: val.fnc,
289
+ })
290
+ })
291
+ /** handler */
292
+ handler.add(index + '', Class)
279
293
  /** 执行初始化 */
280
294
  Class.init && Class.init()
281
295
  this.PluginList[index] = info
@@ -284,9 +298,6 @@ export const PluginLoader = new (class PluginLoader {
284
298
  // if (!lodash.isEmpty(Class.handler)) handler.add({ name, dir, App, Class })
285
299
  /** 注册按钮 */
286
300
  // if (!lodash.isEmpty(Class.button)) button.add({ name, dir, App, Class })
287
- /** 收集插件 */
288
- // const res = this.App(App, Class, { name, dir, path: `${dir}/${name}` })
289
- // this.Apps.push(res)
290
301
  return true
291
302
  })
292
303
  // rule收集并排序
@@ -314,45 +325,15 @@ export const PluginLoader = new (class PluginLoader {
314
325
  * 卸载插件
315
326
  */
316
327
  uninstallApp (dir, name) {
317
- this.Apps = this.Apps.filter((v) => !(v.file.dir === dir && v.file.name === name))
318
- this.uninstallTask(dir, name)
319
- button.del(dir, name)
320
- handler.del({ dir, name, key: '' })
321
- }
322
-
323
- /** 创建定时任务 */
324
- async creatTask () {
325
- this.task.forEach((val, index) => {
326
- if (val.schedule) { return }
327
- val.log = val.log === false ? (log) => logger.debug(log) : (log) => logger.mark(log)
328
- val.schedule = schedule.scheduleJob(val.cron, async () => {
329
- try {
330
- typeof val.log === 'function' && val.log(`[定时任务][${val.file.dir}][${val.name}] 开始执行`)
331
- const App = new val.App()
332
- await App[val.fnc]()
333
- typeof val.log === 'function' && val.log(`[定时任务][${val.file.dir}][${val.name}] 执行完毕`)
334
- } catch (error) {
335
- logger.error(`[定时任务][${val.file.dir}][${val.name}] 执行报错`)
336
- logger.error(error)
337
- }
338
- })
339
- this.task[index] = val
340
- })
341
- }
342
-
343
- /**
344
- * 卸载定时任务
345
- */
346
- uninstallTask (dir, name) {
347
- this.task = this.task.filter((task) => {
348
- if (task.file.dir === dir && task.file.name === name) {
349
- /** 停止定时任务 */
350
- task.schedule && task.schedule.cancel()
351
- /** 移除定时任务 */
352
- return false
353
- }
354
- /** 保留定时任务 */
355
- return true
328
+ // this.Apps = this.Apps.filter((v) => !(v.file.dir === dir && v.file.name === name))
329
+ // this.uninstallTask(dir, name)
330
+ // button.del(dir, name)
331
+ // handler.del({ dir, name, key: '' })
332
+ Object.keys(this.PluginList).forEach(key => {
333
+ const info = this.PluginList[key]
334
+ /** 停止定时任务 */
335
+ info.task.forEach(val => val.schedule?.cancel())
336
+ info.file.dir === dir && info.file.name === name && delete this.PluginList[key]
356
337
  })
357
338
  }
358
339
 
@@ -360,99 +341,94 @@ export const PluginLoader = new (class PluginLoader {
360
341
  * 监听单个文件热更新
361
342
  */
362
343
  watch (dir, name) {
363
- // if (this.watcher.get(`${dir}.${name}`)) return
364
- // const file = `./plugins/${dir}/${name}`
365
- // const watcher = chokidar.watch(file)
366
- // /** 监听修改 */
367
- // watcher.on('change', async () => {
368
- // /** 卸载 */
369
- // this.uninstallApp(dir, name)
370
- // /** 载入插件 */
371
- // const res = await this.createdApp(dir, name, true)
372
- // if (!res) return
373
- // logger.mark(`[修改插件][${dir}][${name}]`)
374
- // })
344
+ if (this.watcher.get(`${dir}.${name}`)) { return }
345
+ const file = `./plugins/${dir}/${name}`
346
+ const watcher = chokidar.watch(file)
347
+ /** 监听修改 */
348
+ watcher.on('change', async () => {
349
+ /** 卸载 */
350
+ this.uninstallApp(dir, name)
351
+ /** 载入插件 */
352
+ const res = await this.createdApp(dir, name, true)
353
+ if (!res) { return }
354
+ logger.mark(`[修改插件][${dir}][${name}]`)
355
+ })
375
356
  /** 监听删除 */
376
- // watcher.on('unlink', async () => {
377
- // /** 卸载 */
378
- // this.uninstallApp(dir, name)
379
- // this.watcher.delete(`${dir}.${name}`)
380
- // logger.mark(`[卸载插件][${dir}][${name}]`)
381
- // })
382
- // this.watcher.set(`${dir}.${name}`, watcher)
357
+ watcher.on('unlink', async () => {
358
+ /** 卸载 */
359
+ this.uninstallApp(dir, name)
360
+ this.watcher.delete(`${dir}.${name}`)
361
+ logger.mark(`[卸载插件][${dir}][${name}]`)
362
+ })
363
+ this.watcher.set(`${dir}.${name}`, watcher)
383
364
  }
384
365
 
385
366
  /**
386
367
  * 监听文件夹更新
387
368
  */
388
- watchDir (dir) {
389
- // if (dir) return
390
- // if (this.watcher.get(dir)) return
391
- // const file = `${this.dir}/${dir}/`
392
- // const watcher = chokidar.watch(file)
393
- // /** 热更新 */
394
- // setTimeout(() => {
395
- // /** 新增文件 */
396
- // watcher.on('add', async filePath => {
397
- // logger.debug(`[热更新][新增插件] ${filePath}`)
398
- // const name = path.basename(filePath) as fileName
399
- // if (!name.endsWith('')) return
400
- // if (!fs.existsSync(`${file}/${name}`)) return
401
- // /** 载入插件 */
402
- // const res = await this.createdApp(dir, name, true)
403
- // if (!res) return
404
- // /** 延迟1秒 等待卸载完成 */
405
- // Common.sleep(1000)
406
- // .then(() => {
407
- // /** 停止整个文件夹监听 */
408
- // watcher.close()
409
- // /** 新增插件之后重新监听文件夹 */
410
- // this.watcher.delete(dir)
411
- // this.watchDir(dir)
412
- // logger.mark(`[新增插件][${dir}][${name}]`)
413
- // return true
414
- // })
415
- // .catch(error => logger.error(error))
416
- // })
417
- // /** 监听修改 */
418
- // watcher.on('change', async PluPath => {
419
- // const name = path.basename(PluPath) as fileName
420
- // if (!name.endsWith('')) return
421
- // if (!fs.existsSync(`${this.dir}/${dir}/${name}`)) return
422
- // /** 卸载 */
423
- // this.uninstallApp(dir, name)
424
- // /** 载入插件 */
425
- // const res = await this.createdApp(dir, name, true)
426
- // if (!res) return
427
- // logger.mark(`[修改插件][${dir}][${name}]`)
428
- // })
429
- // /** 监听删除 */
430
- // watcher.on('unlink', async PluPath => {
431
- // const name = path.basename(PluPath) as fileName
432
- // if (!name.endsWith('')) return
433
- // /** 卸载 */
434
- // this.uninstallApp(dir, name)
435
- // /** 停止监听 */
436
- // watcher.close()
437
- // /** 重新监听文件夹 */
438
- // this.watcher.delete(dir)
439
- // this.watchDir(dir)
440
- // logger.mark(`[卸载插件][${dir}][${name}]`)
441
- // })
442
- // }, 500)
443
- // /** 生成随机数0.5-2秒 */
444
- // const random = Math.floor(Math.random() * 1000) + 500
445
- // Common.sleep(random)
446
- // .then(() => {
447
- // const isExist = this.watcher.get(dir)
448
- // /** 这里需要检查一下是否已经存在,已经存在就关掉之前的监听 */
449
- // if (isExist) {
450
- // isExist.close()
451
- // this.watcher.delete(dir)
452
- // }
453
- // this.watcher.set(dir, watcher)
454
- // return true
455
- // })
456
- // .catch(() => {})
369
+ async watchDir (dir) {
370
+ if (this.watcher.get(dir)) { return }
371
+ const file = `${this.dir}/${dir}/`
372
+ const watcher = chokidar.watch(file)
373
+ /** 热更新 */
374
+ setTimeout(() => {
375
+ /** 新增文件 */
376
+ watcher.on('add', async (filePath) => {
377
+ logger.debug(`[热更新][新增插件] ${filePath}`)
378
+ const name = path.basename(filePath)
379
+ /** js环境仅接受js ts接受两者 */
380
+ if (!this.isTs && !name.endsWith('.js')) { return }
381
+ if (this.isTs && !name.endsWith('.ts') && !name.endsWith('.js')) { return }
382
+ if (!fs.existsSync(`${file}/${name}`)) { return }
383
+ /** 载入插件 */
384
+ const res = await this.createdApp(dir, name, true)
385
+ if (!res) { return }
386
+ /** 延迟1秒 等待卸载完成 */
387
+ await common.sleep(1000)
388
+ /** 停止整个文件夹监听 */
389
+ watcher.close()
390
+ /** 新增插件之后重新监听文件夹 */
391
+ this.watcher.delete(dir)
392
+ this.watchDir(dir)
393
+ logger.mark(`[新增插件][${dir}][${name}]`)
394
+ return true
395
+ })
396
+ /** 监听修改 */
397
+ watcher.on('change', async (PluPath) => {
398
+ const name = path.basename(PluPath)
399
+ if (!name.endsWith('')) { return }
400
+ if (!fs.existsSync(`${this.dir}/${dir}/${name}`)) { return }
401
+ /** 卸载 */
402
+ this.uninstallApp(dir, name)
403
+ /** 载入插件 */
404
+ const res = await this.createdApp(dir, name, true)
405
+ if (!res) { return }
406
+ logger.mark(`[修改插件][${dir}][${name}]`)
407
+ })
408
+ /** 监听删除 */
409
+ watcher.on('unlink', async (PluPath) => {
410
+ const name = path.basename(PluPath)
411
+ if (!name.endsWith('')) { return }
412
+ /** 卸载 */
413
+ this.uninstallApp(dir, name)
414
+ /** 停止监听 */
415
+ watcher.close()
416
+ /** 重新监听文件夹 */
417
+ this.watcher.delete(dir)
418
+ this.watchDir(dir)
419
+ logger.mark(`[卸载插件][${dir}][${name}]`)
420
+ })
421
+ }, 500)
422
+ /** 生成随机数0.5-2秒 */
423
+ const random = Math.floor(Math.random() * 1000) + 500
424
+ await common.sleep(random)
425
+ const isExist = this.watcher.get(dir)
426
+ /** 这里需要检查一下是否已经存在,已经存在就关掉之前的监听 */
427
+ if (isExist) {
428
+ isExist.close()
429
+ this.watcher.delete(dir)
430
+ }
431
+ this.watcher.set(dir, watcher)
432
+ return true
457
433
  }
458
434
  })()
@@ -5,7 +5,7 @@ import { WebSocketServer } from 'ws'
5
5
  import { createServer } from 'http'
6
6
  import express from 'express'
7
7
  import { exec, config, logger, common } from '../utils/index.js'
8
- import { render, HttpRenderer, Wormhole } from '../renderer/index.js'
8
+ import { render, HttpRenderer, Wormhole } from '../render/index.js'
9
9
  export const server = new (class Server {
10
10
  reg
11
11
  list
package/lib/db/level.d.ts CHANGED
@@ -14,5 +14,5 @@ export default class LevelDB extends Level {
14
14
  * @param {string} key 键
15
15
  * @param {object|string} value 值
16
16
  */
17
- set(key: string, value: string): Promise<void>;
17
+ set(key: string, value: string | object): Promise<void>;
18
18
  }
@@ -2,7 +2,7 @@ import lodash from 'lodash'
2
2
  import { review } from './review.handler.js'
3
3
  import EventHandler from './event.handler.js'
4
4
  import { logger, config } from '../utils/index.js'
5
- import { listener, stateArr, PluginLoader } from '../core/index.js'
5
+ import { listener, stateArr, pluginLoader } from '../core/index.js'
6
6
  /**
7
7
  * 消息事件
8
8
  */
@@ -39,8 +39,8 @@ export class MessageHandler extends EventHandler {
39
39
  /** 上下文 */
40
40
  if (await this.context()) { return }
41
41
  /* eslint-disable no-labels */
42
- a: for (const index of PluginLoader.rule) {
43
- const app = PluginLoader.PluginList[index]
42
+ a: for (const index of pluginLoader.ruleIds) {
43
+ const app = pluginLoader.PluginList[index]
44
44
  /** 判断事件 */
45
45
  if (app.event && !this.filtEvent(app.event)) { continue }
46
46
  /** 正则匹配 */
@@ -1,5 +1,5 @@
1
1
  import { KarinMessage } from '../event/index.js';
2
- import { E, PluginApps, GroupCfg } from '../types/index.js';
2
+ import { EType, PluginApps, GroupCfg } from '../types/index.js';
3
3
  /**
4
4
  * 事件拦截器
5
5
  * 利用可执行函数的特性,热更新所有拦截器
@@ -14,12 +14,12 @@ export declare const review: {
14
14
  };
15
15
  App: import("../types/index.js").App;
16
16
  Config: import("../types/index.js").Config;
17
- CD: (e: E, config: GroupCfg) => boolean;
17
+ CD: (e: EType, config: GroupCfg) => boolean;
18
18
  mode: (e: KarinMessage, config: GroupCfg) => boolean;
19
19
  alias: (e: KarinMessage, config: GroupCfg) => boolean;
20
- GroupEnable: (e: E) => boolean;
21
- UserEnable: (e: E) => boolean;
22
- GroupMsgPrint: (e: E) => boolean;
20
+ GroupEnable: (e: EType) => boolean;
21
+ UserEnable: (e: EType) => boolean;
22
+ GroupMsgPrint: (e: EType) => boolean;
23
23
  PluginEnable: (app: PluginApps, config: GroupCfg) => boolean;
24
24
  main(): void;
25
25
  /**