mm_machine 2.3.5 → 2.3.6

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 (4) hide show
  1. package/drive.js +112 -34
  2. package/index.js +12 -13
  3. package/mod.js +13 -8
  4. package/package.json +2 -1
package/drive.js CHANGED
@@ -1,10 +1,17 @@
1
- const {
2
- Mod
3
- } = require('./mod');
1
+ const prettier = require('@prettier/sync');
4
2
  require('mm_tpl');
5
3
  let {
6
4
  conf
7
5
  } = require('mm_config');
6
+ const {
7
+ Mod
8
+ } = require('./mod');
9
+
10
+ if (!$.prettyCode) {
11
+ $.prettyCode = function (code, options) {
12
+ return prettier.format(code, options);
13
+ };
14
+ }
8
15
 
9
16
  /**
10
17
  * 驱动基础类
@@ -95,6 +102,7 @@ Drive.prototype.loadConfig = function (file) {
95
102
  /**
96
103
  * 设置配置
97
104
  * @param {object} config 配置对象
105
+ * @returns {object} 配置项
98
106
  */
99
107
  Drive.prototype.setConfig = function (config) {
100
108
  if (config) {
@@ -153,27 +161,13 @@ Drive.prototype._getTplDir = function () {
153
161
  return this.getParent().getTplDir();
154
162
  };
155
163
 
156
- /**
157
- * 创建脚本
158
- * @param {string} file 文件路径
159
- * @param {object} model 模板数据
160
- * @param {string} tpl_dir 模板文件路径
161
- * @returns {boolean} 创建是否成功
162
- */
163
- Drive.prototype._createScriptFile = function (file, model = {}, tpl_dir = '') {
164
- var tpl = this.getScriptTpl(tpl_dir);
165
- var content = $.tpl.render(tpl, model);
166
- file.saveText(content);
167
- return file;
168
- };
169
-
170
164
  /**
171
165
  * 获取脚本模板
172
166
  * @param {string} tpl_dir 模板文件路径
173
167
  * @returns {string} 脚本模板内容
174
168
  */
175
- Drive.prototype.getScriptTpl = function (tpl_dir = '') {
176
- var f = './script.tpl.js'.fullname(tpl_dir || this._getTplDir());
169
+ Drive.prototype._getScriptTpl = function () {
170
+ var f = './script.tpl.js'.fullname(this._getTplDir());
177
171
  if (f.hasFile()) {
178
172
  return f.loadText();
179
173
  } else {
@@ -201,7 +195,7 @@ Drive.prototype.getScriptTpl = function (tpl_dir = '') {
201
195
  };
202
196
 
203
197
  /**
204
- * 移除脚本
198
+ * 移除加载的脚本模块
205
199
  */
206
200
  Drive.prototype._remove = function () {
207
201
  let file = this._getScriptFile();
@@ -220,7 +214,7 @@ Drive.prototype._remove = function () {
220
214
  }
221
215
  }
222
216
  } catch (err) {
223
- this.log('error', `移除脚本失败: `, err);
217
+ this.log('error', `移除加载的脚本模块失败: `, err);
224
218
  }
225
219
  };
226
220
 
@@ -255,7 +249,6 @@ Drive.prototype.unloadCore = async function (remove) {
255
249
 
256
250
  /**
257
251
  * 获取脚本文件路径
258
- * @param {string} file 文件路径
259
252
  * @returns {string | null} 完整文件路径
260
253
  */
261
254
  Drive.prototype._getScriptFile = function () {
@@ -266,10 +259,67 @@ Drive.prototype._getScriptFile = function () {
266
259
  if (!filename.hasFile()) {
267
260
  this.newScript(filename);
268
261
  }
269
-
270
262
  return filename;
271
263
  };
272
264
 
265
+ /**
266
+ * 新建脚本文件
267
+ * @param {string} file 目标文件路径
268
+ */
269
+ Drive.prototype.newScript = function (file) {
270
+ this._createScriptFile(file, this.config);
271
+ };
272
+
273
+ /**
274
+ * 创建脚本
275
+ * @param {string} file 文件路径
276
+ * @param {object} model 模板数据
277
+ * @returns {boolean} 创建是否成功
278
+ */
279
+ Drive.prototype._createScriptFile = function (file, model = {}) {
280
+ var tpl = this._getScriptTpl();
281
+ var content = $.tpl.render(tpl, model);
282
+ if (!content) {
283
+ return '';
284
+ }
285
+ let code = this.prettyCode(content, 'js');
286
+ file.saveText(code);
287
+ return file;
288
+ };
289
+
290
+ /**
291
+ * 获取脚本模板
292
+ * @param {string} tpl_dir 模板文件路径
293
+ * @returns {string} 脚本模板内容
294
+ */
295
+ Drive.prototype._getScriptTpl = function () {
296
+ var f = './script.tpl.js'.fullname(this._getTplDir());
297
+ if (f.hasFile()) {
298
+ return f.loadText();
299
+ } else {
300
+ return `module.exports = {
301
+ /**
302
+ * 初始化
303
+ */
304
+ async _init() {
305
+ this.log('debug', \`初始化!\`);
306
+ },
307
+ /**
308
+ * 销毁
309
+ */
310
+ async _destroy(...args) {
311
+ this.log('debug', \`销毁!\`);
312
+ },
313
+ /**
314
+ * 主要逻辑
315
+ */
316
+ async main(...args) {
317
+ // 主要代码写在这
318
+ }
319
+ }`;
320
+ }
321
+ };
322
+
273
323
  /**
274
324
  * 加载脚本文件,支持热重载模式
275
325
  * 在开发模式(mode=3或4)下使用 $.require 进行热重载
@@ -333,25 +383,53 @@ Drive.prototype.newConfig = function (file) {
333
383
  this._createConfigFile(file);
334
384
  };
335
385
 
386
+ /**
387
+ * 预试代码
388
+ * @param {string} code 要预试的代码
389
+ * @param {string} type 预试类型,可选"json"或"js"
390
+ * @returns {string} 预试后的代码字符串
391
+ */
392
+ Drive.prototype.prettyCode = function (code, type = 'json5') {
393
+ let options = {
394
+ tabWidth: 2
395
+ };
396
+ switch (type) {
397
+ case 'json5':
398
+ options.parser = 'json5';
399
+ break;
400
+ case 'js':
401
+ case 'javascript':
402
+ options.parser = 'babel';
403
+ options.semi = true; // 在语句末尾添加分号
404
+ options.singleQuote = true; // 使用单引号
405
+ break;
406
+ default:
407
+ options.parser = 'json';
408
+ break;
409
+ }
410
+ let new_code = $.prettyCode(code, options);
411
+ return new_code;
412
+ };
413
+
336
414
  /**
337
415
  * 创建配置文件
338
416
  * @param {string} file 目标文件路径
339
417
  * @returns {string} 配置文件内容
340
418
  */
341
419
  Drive.prototype._createConfigFile = function (file) {
342
- var tpl = this.getConfigTpl();
420
+ var tpl = this._getConfigTpl();
343
421
  var content = $.tpl.render(tpl, this.config);
344
- file.saveText(content);
422
+ let code = this.prettyCode(content, 'json');
423
+ file.saveText(code);
345
424
  return file;
346
425
  };
347
426
 
348
427
  /**
349
428
  * 获取配置模板
350
- * @param {string} tpl_dir 模板文件路径
351
429
  * @returns {string} 配置模板内容
352
430
  */
353
- Drive.prototype.getConfigTpl = function (tpl_dir = '') {
354
- var f = './config.tpl.json'.fullname(tpl_dir || this._getTplDir());
431
+ Drive.prototype._getConfigTpl = function () {
432
+ var f = './config.tpl.json'.fullname(this._getTplDir());
355
433
  if (f.hasFile()) {
356
434
  return f.loadText();
357
435
  } else {
@@ -370,8 +448,8 @@ Drive.prototype.getConfigTpl = function (tpl_dir = '') {
370
448
  "state": \${state || 1},
371
449
  // 模块排序,可选,默认100
372
450
  "sort": \${sort || 100},
373
- // 是否结束,可选,默认false
374
- "end": \${end || false}
451
+ // 是否结束,可选,默认false
452
+ "end": \${end || false}
375
453
  }`;
376
454
  }
377
455
  };
@@ -543,8 +621,8 @@ Drive.prototype.loadBefore = async function () {
543
621
  * 加载处理
544
622
  */
545
623
  Drive.prototype._loadCore = async function () {
546
- this.loadConfig();
547
- this.loadScript();
624
+ await this.loadConfig();
625
+ await this.loadScript();
548
626
  };
549
627
 
550
628
  /**
@@ -569,13 +647,13 @@ Drive.prototype.save = function () {
569
647
  // 如果不存在,添加新配置项
570
648
  config.push(this.config);
571
649
  }
572
- file.saveText(JSON.stringify(config, null, 4));
650
+ file.saveText(JSON.stringify(config, null, 2));
573
651
  return;
574
652
  }
575
653
  }
576
654
 
577
655
  // 单对象格式配置,直接保存
578
- file.saveText(JSON.stringify(this.config, null, 4));
656
+ file.saveText(JSON.stringify(this.config, null, 2));
579
657
  } catch (err) {
580
658
  this.log('error', `保存配置失败: `, err);
581
659
  }
package/index.js CHANGED
@@ -46,17 +46,15 @@ class Manager extends Mod {
46
46
  */
47
47
  dir: './ai/manager'.fullname(),
48
48
  /**
49
- * 类型 script脚本 | json配置 | drive驱动
49
+ * 搜索模式 dir按目录搜索 | file按文件名搜索
50
50
  * @type {string}
51
51
  */
52
- mod_type: 'drive',
52
+ search_way: 'file',
53
53
  /**
54
- * 搜索模式
55
- * dir 按目录搜索
56
- * file 按文件名搜索
54
+ * 类型 script脚本 | json配置 | drive驱动
57
55
  * @type {string}
58
56
  */
59
- search_way: 'file',
57
+ mod_type: 'drive',
60
58
  /**
61
59
  * 是否懒加载
62
60
  * @type {boolean}
@@ -383,7 +381,7 @@ Manager.prototype._getDirName = function () {
383
381
  // 后缀,为配置项名称
384
382
  let name = this.config.name.toLowerCase();
385
383
  // 目录名,为前缀加下划线加后缀
386
- return prefix + "_" + name;
384
+ return prefix + '_' + name;
387
385
  };
388
386
 
389
387
  /**
@@ -394,10 +392,11 @@ Manager.prototype._getDirName = function () {
394
392
  Manager.prototype._getAllDirFiles = function (dir) {
395
393
  let files = [];
396
394
  let dirs = $.dir.getAll(dir, this._getDirName());
397
- for (let d of dirs) {
398
- let list = $.file.getAll(d, this.config.filename);
399
- if (list.length > 0) {
400
- files.push(...list);
395
+ for (let i = 0; i < dirs.length; i++) {
396
+ let d = dirs[i];
397
+ let lt = $.file.getAll(d, this.config.filename);
398
+ if (lt.length > 0) {
399
+ files.push(...lt);
401
400
  }
402
401
  }
403
402
  return files;
@@ -465,7 +464,7 @@ Manager.prototype.update = async function (dir, clear = true) {
465
464
  }
466
465
 
467
466
  // 查找所有json文件
468
- let files = this._findFiles(dir);
467
+ let files = this._findFiles(dir || this.config.dir);
469
468
  // 批量注册模块
470
469
  this.batchRegister(files);
471
470
  // 更新配置信息
@@ -593,7 +592,7 @@ Manager.prototype._runSub = async function (mod, method, ...params) {
593
592
 
594
593
  return ret;
595
594
  } catch (err) {
596
- $.log.error(`[${this.type}] 执行模块方法失败: `, err);
595
+ $.log.error(`执行模块方法失败: `, err);
597
596
  return null;
598
597
  }
599
598
  };
package/mod.js CHANGED
@@ -142,10 +142,8 @@ Mod.prototype._onDestroy = function () {
142
142
  * @param {object} ctx 上下文对象
143
143
  */
144
144
  Mod.prototype._onLoad = async function (ctx) {
145
- let status_last = 'created';
146
145
  // 1. 加载
147
146
  this.on('load:before', async (ctx) => {
148
- status_last = this.getState();
149
147
  this.setState('loading');
150
148
  await this._loadCore(...ctx.params);
151
149
  });
@@ -222,13 +220,19 @@ Mod.prototype._onUnload = async function (ctx) {
222
220
  };
223
221
 
224
222
  /**
225
- * 初始化监听
223
+ * 初始化监听事件
224
+ * @param {object} ctx 上下文对象
226
225
  */
227
226
  Mod.prototype._onDestroy = async function (ctx) {
228
227
  let status_last = 'unloaded';
228
+ // 6. 销毁
229
+ this.on('destroy:before', async (ctx) => {
230
+ status_last = this.getState();
231
+ this.setState('destroying');
232
+ });
229
233
  this.on('destroy:check', (ctx) => {
230
234
  if (status_last !== 'unloaded') {
231
- status_last = this.getState();
235
+ this.setState(status_last);
232
236
  ctx.error = new Error('销毁前必须先卸载');
233
237
  }
234
238
  });
@@ -354,7 +358,7 @@ Mod.prototype.main = async function (...args) {
354
358
  throw new Error(`方法${method}不存在`);
355
359
  }
356
360
  let params = args.slice(1);
357
- return await this.methods[method](...params);
361
+ return await this.methods[method](...params);
358
362
  };
359
363
 
360
364
  /**
@@ -371,7 +375,8 @@ Mod.prototype.setMethods = function (methods) {
371
375
 
372
376
  /**
373
377
  * 设置脚本方法
374
- * @param {object} methods 脚本方法对象
378
+ * @param {string} method 方法名
379
+ * @param {Function} func 方法函数
375
380
  */
376
381
  Mod.prototype.setMethod = function (method, func) {
377
382
  if (!func) throw new Error(`函数(func)不能为空`);
@@ -448,9 +453,9 @@ Mod.prototype._callBefore = async function (method, params) {
448
453
  * @returns {Promise<any>} 主方法结果
449
454
  */
450
455
  Mod.prototype._callMain = async function (method_func, params, result) {
451
- let method_result = await method_func.call(this._mod || this, ...params);
456
+ let ret = await method_func.call(this._mod || this, ...params);
452
457
  // 修复:如果主方法返回undefined,则使用前置钩子的结果
453
- return method_result !== undefined ? method_result : result;
458
+ return ret !== undefined ? ret : result;
454
459
  };
455
460
 
456
461
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mm_machine",
3
- "version": "2.3.5",
3
+ "version": "2.3.6",
4
4
  "description": "A flexible Node.js plugin mechanism system for dynamic loading, management and execution of modules. Supports hot reload, lifecycle management, and modern JavaScript features.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -33,6 +33,7 @@
33
33
  "README.md"
34
34
  ],
35
35
  "dependencies": {
36
+ "@prettier/sync": "^0.6.1",
36
37
  "mm_config": "^2.3.0",
37
38
  "mm_hot_reload": "^1.3.0",
38
39
  "mm_tpl": "^2.4.9"