mm_machine 2.0.5 → 2.0.7

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/README.md CHANGED
@@ -44,7 +44,7 @@ async function init() {
44
44
  });
45
45
 
46
46
  // 加载所有模块
47
- await engine.load_list();
47
+ await engine.loads();
48
48
 
49
49
  // 执行所有模块的main方法
50
50
  const results = await engine.execute('main');
@@ -162,7 +162,7 @@ const engine = new Machine();
162
162
  // 初始化引擎
163
163
  async function init() {
164
164
  // 加载模块
165
- await engine.load_list();
165
+ await engine.loads();
166
166
 
167
167
  // 执行所有模块的main方法
168
168
  await engine.execute('main');
@@ -306,7 +306,7 @@ engine.update_config_all({
306
306
  });
307
307
 
308
308
  // 然后加载模块
309
- await engine.load_list();
309
+ await engine.loads();
310
310
  ```
311
311
 
312
312
  ### 示例3:实现热更新和动态管理
@@ -322,7 +322,7 @@ engine.mode = 2;
322
322
  // 初始化
323
323
  async function setup() {
324
324
  // 加载模块
325
- await engine.load_list();
325
+ await engine.loads();
326
326
 
327
327
  // 开始监听文件变化
328
328
  engine.watch();
@@ -357,7 +357,7 @@ const engine = new Machine();
357
357
  async function run() {
358
358
  try {
359
359
  // 加载模块并捕获可能的错误
360
- await engine.load_list();
360
+ await engine.loads();
361
361
 
362
362
  // 安全地执行模块方法
363
363
  try {
@@ -1,28 +1,61 @@
1
- var counter = 0;
2
-
3
- function test() {
1
+ /**
2
+ * 计数器变量
3
+ * @type {number}
4
+ */
5
+ var counter = 200;
6
+
7
+ /**
8
+ * 测试函数
9
+ * @private
10
+ */
11
+ function _test() {
4
12
  console.log("测试模块1执行", counter++);
5
13
  }
6
14
 
15
+ /**
16
+ * 主函数
17
+ * @returns {Object} 返回执行结果
18
+ * @returns {string} return.message - 消息内容
19
+ * @returns {number} return.value - 计数器值
20
+ */
7
21
  function main() {
8
- test();
22
+ _test();
9
23
  return { message: "测试模块1返回", value: counter };
10
24
  }
11
25
 
12
26
  exports.main = main;
13
27
 
28
+ /**
29
+ * 主函数执行前的钩子函数
30
+ * @returns {void}
31
+ */
14
32
  exports.main_before = function() {
15
33
  console.log("测试模块1前置钩子");
16
34
  };
17
35
 
36
+ /**
37
+ * 主函数执行后的钩子函数
38
+ * @param {Object} ret - 主函数返回值
39
+ * @param {string} ret.message - 消息内容
40
+ * @param {number} ret.value - 计数器值
41
+ * @returns {Promise<void>}
42
+ */
18
43
  exports.main_after = async function(ret) {
19
44
  console.log("测试模块1后置钩子", ret);
20
45
  };
21
46
 
47
+ /**
48
+ * 模块加载时的钩子函数
49
+ * @returns {void}
50
+ */
22
51
  exports.load = function() {
23
52
  console.log("加载测试模块1");
24
53
  };
25
54
 
55
+ /**
56
+ * 模块初始化时的钩子函数
57
+ * @returns {void}
58
+ */
26
59
  exports.init = function() {
27
60
  console.log("初始化测试模块1");
28
61
  };
@@ -1,3 +1,10 @@
1
+ /**
2
+ * 主函数执行后的钩子函数
3
+ * @param {Object} ret - 主函数返回值
4
+ * @param {string} ret.result - 执行结果
5
+ * @param {number} ret.count - 计数器值
6
+ * @returns {Object} 返回处理后的结果
7
+ */
1
8
  exports.main_after = function(ret) {
2
9
  console.log("测试模块2后置处理", ret);
3
10
  return ret;
@@ -0,0 +1,17 @@
1
+
2
+ /**
3
+ * 导入主模块
4
+ */
5
+ var mainModule = require('./main.js');
6
+
7
+ /**
8
+ * 导入后置处理模块
9
+ */
10
+ var afterModule = require('./after.js');
11
+
12
+ /**
13
+ * 合并模块导出
14
+ */
15
+ Object.assign(exports, mainModule, afterModule);
16
+
17
+ console.log("测试模块2入口文件已加载");
package/app/test2/main.js CHANGED
@@ -1,5 +1,15 @@
1
+ /**
2
+ * 计数器变量
3
+ * @type {number}
4
+ */
1
5
  var count = 0;
2
6
 
7
+ /**
8
+ * 主函数
9
+ * @returns {Object} 返回执行结果
10
+ * @returns {string} return.result - 执行结果
11
+ * @returns {number} return.count - 计数器值
12
+ */
3
13
  function main() {
4
14
  console.log("测试模块2执行", count++);
5
15
  return { result: "测试模块2结果", count: count };
@@ -7,10 +17,18 @@ function main() {
7
17
 
8
18
  exports.main = main;
9
19
 
20
+ /**
21
+ * 模块加载时的钩子函数
22
+ * @returns {void}
23
+ */
10
24
  exports.load = function() {
11
25
  console.log("加载测试模块2");
12
26
  };
13
27
 
28
+ /**
29
+ * 模块初始化时的钩子函数
30
+ * @returns {void}
31
+ */
14
32
  exports.init = function() {
15
33
  console.log("初始化测试模块2");
16
34
  };
@@ -1,7 +1,7 @@
1
1
  var i = 0;
2
2
 
3
3
  function test() {
4
- console.log("你好7654321", i++)
4
+ console.log("你好123", i++)
5
5
  }
6
6
 
7
7
  function main() {
@@ -1,11 +1,30 @@
1
+ /**
2
+ * Demo类
3
+ * @class
4
+ */
1
5
  class Demo {
2
6
  constructor() {}
3
7
  }
4
- var i = 0;
8
+
9
+ /**
10
+ * 计数器
11
+ * @type {number}
12
+ */
13
+ var counter = 0;
14
+
15
+ /**
16
+ * 主函数
17
+ * @returns {number} 返回计数器值
18
+ */
5
19
  Demo.prototype.main = function() {
6
- console.log("我很好7654321", i++);
7
- return i;
20
+ console.log("我很好7654321", counter++);
21
+ return counter;
8
22
  }
23
+
24
+ /**
25
+ * 初始化函数
26
+ * @returns {void}
27
+ */
9
28
  Demo.prototype.init = function(){
10
29
  console.log("初始化test2");
11
30
  }
package/index.js CHANGED
@@ -56,7 +56,7 @@ class Index {
56
56
  * @returns {Promise<any>} 执行结果
57
57
  * @private
58
58
  */
59
- async _executeMethod(module, method, params = []) {
59
+ async _execute(module, method, params = []) {
60
60
  if (!module || !method) return null;
61
61
 
62
62
  try {
@@ -66,15 +66,14 @@ class Index {
66
66
  }
67
67
 
68
68
  // 执行方法
69
- const ret = module.exec(method, ...params);
70
- const result = util.types.isPromise(ret) ? await ret : ret;
69
+ const ret = await module.exec(method, ...params);
71
70
 
72
71
  // 根据模式决定是否重载
73
72
  if (this.mode >= 4) {
74
73
  module.exec('reload');
75
74
  }
76
75
 
77
- return result;
76
+ return ret;
78
77
  } catch (err) {
79
78
  $.log.error(`执行模块方法失败: ${err.message}`);
80
79
  return null;
@@ -101,9 +100,9 @@ Index.prototype.Drive = Item;
101
100
  * @param {String} file 配置文件
102
101
  * @returns {Promise<Object|null>} 加载的驱动或配置对象
103
102
  */
104
- Index.prototype.load_item = async function(dir, cg, file) {
103
+ Index.prototype.loadItem = async function(dir, cg, file) {
105
104
  if (!dir || !file) {
106
- $.log.error('load_item: 缺少必要参数');
105
+ $.log.error('load: 缺少必要参数');
107
106
  return null;
108
107
  }
109
108
 
@@ -112,10 +111,10 @@ Index.prototype.load_item = async function(dir, cg, file) {
112
111
  const drive = new this.Drive(dir, this.dir_base.fullname());
113
112
  drive.mode = this.mode;
114
113
  if (cg) {
115
- await drive.exec('load_config', file, cg.name);
116
- await drive.exec('set_config', cg);
114
+ await drive.exec('loadConfig', file, cg.name);
115
+ await drive.exec('setConfig', cg);
117
116
  } else {
118
- await drive.exec('load_config', file);
117
+ await drive.exec('loadConfig', file);
119
118
  }
120
119
  this.list.push(drive);
121
120
  return drive;
@@ -144,16 +143,16 @@ Index.prototype.load_item = async function(dir, cg, file) {
144
143
  * @param {Array} list 文件列表
145
144
  * @returns {Promise<void>}
146
145
  */
147
- Index.prototype.load_list = async function(list) {
146
+ Index.prototype.loads = async function(list) {
148
147
  // 遍历文件路径
149
148
  if (!Array.isArray(list)) {
150
- $.log.error('load_list: 列表参数必须是数组');
149
+ $.log.error('loads: 列表参数必须是数组');
151
150
  return;
152
151
  }
153
152
 
154
153
  // 使用for...of和async/await以保证正确的执行顺序
155
154
  for (const file of list) {
156
- await this.load_file(file, true);
155
+ await this.loadFile(file, true);
157
156
  }
158
157
  };
159
158
 
@@ -188,7 +187,7 @@ Index.prototype.update_after = async function(dir) {
188
187
  * @param {Boolean} accurate 精准路径,默认为false
189
188
  * @returns {Promise<void>}
190
189
  */
191
- Index.prototype.update_config_all = async function(searchPath, accurate) {
190
+ Index.prototype.updateConfigAll = async function(searchPath, accurate) {
192
191
  try {
193
192
  // 规范化路径
194
193
  let normalizedPath = searchPath;
@@ -214,16 +213,14 @@ Index.prototype.update_config_all = async function(searchPath, accurate) {
214
213
  const config_file = `${this.type}.json`.fullname(f);
215
214
  if (config_file && config_file.hasFile && config_file.hasFile()) {
216
215
  // 直接加载这个文件
217
- await this.load_file(config_file, true);
218
- $.log.debug(`成功加载配置文件: ${config_file}`);
216
+ await this.loadFile(config_file, true);
219
217
  }
220
218
 
221
219
  // 同时也检查config_demo.json文件
222
220
  const config_file2 = `config_${this.type}.json`.fullname(f);
223
221
  if (config_file2 && config_file2.hasFile && config_file2.hasFile()) {
224
222
  // 直接加载这个文件
225
- await this.load_file(config_file2, true);
226
- $.log.debug(`成功加载配置文件: ${config_file2}`);
223
+ await this.loadFile(config_file2, true);
227
224
  }
228
225
  }
229
226
  } catch (err) {
@@ -232,10 +229,11 @@ Index.prototype.update_config_all = async function(searchPath, accurate) {
232
229
  };
233
230
 
234
231
  /**
235
- * 更新配置
236
- * @param {Object} dir
232
+ * 更新已有配置文件
233
+ * @param {string} dir 目录路径
234
+ * @returns {Promise<void>}
237
235
  */
238
- Index.prototype.update_config_have = async function(dir) {
236
+ Index.prototype.updateConfigHave = async function(dir) {
239
237
  const list = this.list;
240
238
  for (const o of list) {
241
239
  const file = o.filename;
@@ -267,14 +265,14 @@ Index.prototype.update_config_have = async function(dir) {
267
265
  * @param {Boolean} clear - 是否清除现有配置,默认为false
268
266
  * @returns {Promise<void>}
269
267
  */
270
- Index.prototype.update_config = async function(dir, accurate = false, clear = false) {
268
+ Index.prototype.updateConfig = async function(dir, accurate = false, clear = false) {
271
269
  try {
272
270
  if (clear) {
273
271
  this.clear();
274
- await this.update_config_all(dir, accurate);
272
+ await this.updateConfigAll(dir, accurate);
275
273
  } else {
276
274
  // 如果没有指定目录,则更新已有的配置文件
277
- await this.update_config_have();
275
+ await this.updateConfigHave();
278
276
  }
279
277
  this.sort();
280
278
  } catch (err) {
@@ -286,7 +284,7 @@ Index.prototype.update_config = async function(dir, accurate = false, clear = fa
286
284
  * 更新JS
287
285
  * @returns {Promise<void>}
288
286
  */
289
- Index.prototype.update_script = async function() {
287
+ Index.prototype.updateScript = async function() {
290
288
  const list = this.list;
291
289
  for (const o of list) {
292
290
  if (o.config?.state === 1) {
@@ -304,9 +302,9 @@ Index.prototype.update_script = async function() {
304
302
  * @returns {Promise<void>}
305
303
  */
306
304
  Index.prototype.update_main = async function(dir, accurate = false, loadJS = true, clear = true) {
307
- await this.update_config(dir, accurate, clear);
305
+ await this.updateConfig(dir, accurate, clear);
308
306
  if (loadJS) {
309
- await this.update_script();
307
+ await this.updateScript();
310
308
  }
311
309
  };
312
310
 
@@ -484,7 +482,7 @@ Index.prototype.reload = async function(name) {
484
482
  * @param {Boolean} create 不存在则进行创建
485
483
  * @returns {Promise<Object|null|String>} 加载的驱动对象、null或错误信息
486
484
  */
487
- Index.prototype.load_file = async function(file, create = false) {
485
+ Index.prototype.loadFile = async function(file, create = false) {
488
486
  try {
489
487
  const dir = file.dirname();
490
488
  // 载入文件
@@ -493,13 +491,13 @@ Index.prototype.load_file = async function(file, create = false) {
493
491
  if (Array.isArray(obj)) {
494
492
  for (const o of obj) {
495
493
  // 实例化一个驱动
496
- await this.load_item(dir, o, file);
494
+ await this.loadItem(dir, o, file);
497
495
  }
498
496
  } else {
499
- return await this.load_item(dir, null, file);
497
+ return await this.loadItem(dir, null, file);
500
498
  }
501
499
  } else if (create) {
502
- return await this.load_item(dir, null, file);
500
+ return await this.loadItem(dir, null, file);
503
501
  } else {
504
502
  return `${file}文件不存在`;
505
503
  }
@@ -520,12 +518,15 @@ Index.prototype.load_file = async function(file, create = false) {
520
518
  Index.prototype.run = async function(name, method, ...params) {
521
519
  if (name) {
522
520
  const module = await this.get(name);
523
- return module && module.config?.state === 1 ? this._executeMethod(module, method, params) : null;
521
+ if (module && module.config?.state === 1) {
522
+ return await this._execute(module, method, params);
523
+ }
524
+ return null;
524
525
  } else if (name === null) {
525
526
  let result = null;
526
527
  for (const module of this.list) {
527
528
  if (module.config?.state === 1) {
528
- result = await this._executeMethod(module, method, params);
529
+ result = await this._execute(module, method, params);
529
530
  if (result && module.config?.end) {
530
531
  break;
531
532
  }
@@ -546,11 +547,19 @@ Index.prototype.run = async function(name, method, ...params) {
546
547
  Index.prototype.exec = async function(name, method, ...params) {
547
548
  if (name) {
548
549
  const module = await this.get(name);
549
- return module ? this._executeMethod(module, method, params) : null;
550
+ if (module) {
551
+ return await this._execute(module, method, params);
552
+ }
553
+ return null;
550
554
  } else if (name === null) {
555
+ let result = null;
551
556
  for (const module of this.list) {
552
- await this._executeMethod(module, method, params);
557
+ result = await this._execute(module, method, params);
558
+ if (result && module.config?.end) {
559
+ break;
560
+ }
553
561
  }
562
+ return result;
554
563
  }
555
564
  return null;
556
565
  };
package/item.js CHANGED
@@ -115,7 +115,7 @@ class Item {
115
115
  * 设置配置
116
116
  * @param {Object} config 配置对象
117
117
  */
118
- Item.prototype.set_config = function (config) {
118
+ Item.prototype.setConfig = function (config) {
119
119
  if (!config) return;
120
120
 
121
121
  // 如果func_file改变,重置加载状态
@@ -130,7 +130,7 @@ Item.prototype.set_config = function (config) {
130
130
  /**
131
131
  * 设置配置后钩子方法
132
132
  */
133
- Item.prototype.set_config_after = function () {
133
+ Item.prototype.setConfig_after = function () {
134
134
  // 空实现,供子类重写
135
135
  };
136
136
 
@@ -138,8 +138,8 @@ Item.prototype.set_config_after = function () {
138
138
  * 新建脚本文件
139
139
  * @param {String} file 目标文件路径
140
140
  */
141
- Item.prototype.new_script = function (file) {
142
- const templateFile = `${this.dir_base}/script.js`;
141
+ Item.prototype.newScript = function (file) {
142
+ const templateFile = './script.js'.fullname(this.dir_base);
143
143
  if (templateFile.hasFile()) {
144
144
  templateFile.copyFile(file);
145
145
  }
@@ -149,7 +149,7 @@ Item.prototype.new_script = function (file) {
149
149
  * 移除模块
150
150
  * @param {Object|String} module 模块对象或路径
151
151
  */
152
- Item.prototype.remove_module = function (module) {
152
+ Item.prototype._remove = function (module) {
153
153
  if (!module) return;
154
154
 
155
155
  try {
@@ -171,9 +171,9 @@ Item.prototype.remove_module = function (module) {
171
171
 
172
172
  /**
173
173
  * 卸载脚本
174
- * @param {String} file 文件路径
174
+ * @param {string} file 脚本文件路径
175
175
  */
176
- Item.prototype.unload_script = function (file) {
176
+ Item.prototype.unloadScript = function (file) {
177
177
  if (!file) {
178
178
  const funcFile = this.config.func_file;
179
179
  if (funcFile) {
@@ -182,18 +182,18 @@ Item.prototype.unload_script = function (file) {
182
182
  }
183
183
 
184
184
  if (file) {
185
- this.remove_module(file);
185
+ this._remove(file);
186
186
  }
187
187
 
188
188
  this.complete = false;
189
189
  };
190
190
 
191
191
  /**
192
- * 重载脚本
192
+ * 重新加载脚本
193
193
  */
194
- Item.prototype.reload_script = function () {
195
- this.unload_script();
196
- this.load_script();
194
+ Item.prototype.reloadScript = function () {
195
+ this.unloadScript();
196
+ this.loadScript();
197
197
  };
198
198
 
199
199
  /**
@@ -209,9 +209,9 @@ Item.prototype.unload = async function () {
209
209
  */
210
210
  Item.prototype.unload_after = async function (remove) {
211
211
  // 删除脚本
212
- this.unload_script();
212
+ this.unloadScript();
213
213
  if (remove) {
214
- this.remove_file();
214
+ this.removeFile();
215
215
  }
216
216
  };
217
217
 
@@ -221,13 +221,13 @@ Item.prototype.unload_after = async function (remove) {
221
221
  * @param {String} name 函数名
222
222
  * @returns {Object|null} 返回加载的模块对象
223
223
  */
224
- Item.prototype.load_script = function (file, name = '') {
224
+ Item.prototype.loadScript = function (file, name = '') {
225
225
  if (!file) {
226
226
  const funcFile = this.config.func_file;
227
227
  if (funcFile) {
228
228
  file = funcFile.fullname(this.dir);
229
229
  if (!file.hasFile()) {
230
- this.new_script(file);
230
+ this.newScript(file);
231
231
  }
232
232
  } else {
233
233
  return null;
@@ -277,8 +277,8 @@ Item.prototype.load_script = function (file, name = '') {
277
277
  * 新建配置文件
278
278
  * @param {String} file 目标文件路径
279
279
  */
280
- Item.prototype.new_config = function (file) {
281
- const templateFile = `${this.dir_base}/config.tpl.json`;
280
+ Item.prototype.newConfig = function (file) {
281
+ const templateFile = './config.tpl.json'.fullname(this.dir_base);
282
282
  templateFile.copyFile(file);
283
283
  };
284
284
 
@@ -288,7 +288,7 @@ Item.prototype.new_config = function (file) {
288
288
  * @param {String} name 配置项名称
289
289
  * @return {Object|null} 配置对象
290
290
  */
291
- Item.prototype.load_file = function (file, name) {
291
+ Item.prototype.loadFile = function (file, name) {
292
292
  let config = null;
293
293
  try {
294
294
  const fullPath = file.fullname(this.dir);
@@ -296,7 +296,7 @@ Item.prototype.load_file = function (file, name) {
296
296
 
297
297
  // 如果文件不存在,创建新的配置文件
298
298
  if (!text) {
299
- this.new_config(fullPath);
299
+ this.newConfig(fullPath);
300
300
  text = fullPath.loadText();
301
301
  }
302
302
 
@@ -310,18 +310,18 @@ Item.prototype.load_file = function (file, name) {
310
310
  // 在数组中查找匹配的配置项
311
311
  const targetConfig = loadedConfig.find(item => item.name === this.config.name);
312
312
  if (targetConfig) {
313
- this.set_config(targetConfig);
314
- this.set_config_after();
313
+ this.setConfig(targetConfig);
314
+ this.setConfig_after();
315
315
  // 根据模式决定是否重新加载脚本
316
316
  if (this.mode === 3 || this.mode === 4) {
317
- this.reload_script();
317
+ this.reloadScript();
318
318
  }
319
319
  }
320
320
  } else {
321
- this.set_config(loadedConfig);
322
- this.set_config_after();
321
+ this.setConfig(loadedConfig);
322
+ this.setConfig_after();
323
323
  if (this.mode === 3 || this.mode === 4) {
324
- this.reload_script();
324
+ this.reloadScript();
325
325
  }
326
326
  }
327
327
  } catch (err) {
@@ -352,7 +352,7 @@ Item.prototype.load_file = function (file, name) {
352
352
  /**
353
353
  * 删除目录
354
354
  */
355
- Item.prototype.del_dir = function () {
355
+ Item.prototype.delDir = function () {
356
356
  const funcFile = this.config.func_file;
357
357
  if (funcFile && $.dir && $.dir.del) {
358
358
  $.dir.del(this.dir);
@@ -363,7 +363,7 @@ Item.prototype.del_dir = function () {
363
363
  * 删除配置和脚本文件
364
364
  * @returns {String|null} 错误消息,如果没有错误则返回null
365
365
  */
366
- Item.prototype.remove_file = function () {
366
+ Item.prototype.removeFile = function () {
367
367
  const name = this.config.name;
368
368
  const file = this.filename;
369
369
 
@@ -378,7 +378,7 @@ Item.prototype.remove_file = function () {
378
378
  // 在数组配置中查找并删除指定项
379
379
  const index = config.findIndex(item => item.name === name);
380
380
  if (index !== -1) {
381
- this.del_dir();
381
+ this.delDir();
382
382
  config.splice(index, 1);
383
383
  }
384
384
  // 根据剩余配置决定保存或删除文件
@@ -389,10 +389,10 @@ Item.prototype.remove_file = function () {
389
389
  }
390
390
  } else {
391
391
  // 单个配置直接删除目录
392
- this.del_dir();
392
+ this.delDir();
393
393
  }
394
394
  } else {
395
- this.del_dir();
395
+ this.delDir();
396
396
  }
397
397
  } else {
398
398
  errorMessage = '配置文件不存在';
@@ -410,21 +410,21 @@ Item.prototype.remove_file = function () {
410
410
  * @param {Object|String} configData 配置对象或配置路径
411
411
  * @param {String} name 配置名称
412
412
  */
413
- Item.prototype.load_config = function (configData, name) {
413
+ Item.prototype.loadConfig = function (configData, name) {
414
414
  let config;
415
415
  try {
416
416
  if (configData) {
417
417
  if (typeof configData === 'string') {
418
- config = this.load_file(configData, name);
418
+ config = this.loadFile(configData, name);
419
419
  } else {
420
420
  config = configData;
421
421
  }
422
422
  } else {
423
- config = this.load_file(this.filename, name);
423
+ config = this.loadFile(this.filename, name);
424
424
  }
425
425
 
426
- this.set_config(config);
427
- this.set_config_after();
426
+ this.setConfig(config);
427
+ this.setConfig_after();
428
428
  } catch (err) {
429
429
  $.log.error(`载入配置失败: ${err.message}`);
430
430
  }
@@ -435,7 +435,7 @@ Item.prototype.load_config = function (configData, name) {
435
435
  */
436
436
  Item.prototype.load_before = async function () {
437
437
  try {
438
- const module = this.load_script();
438
+ const module = this.loadScript();
439
439
  if (module) {
440
440
  this.complete = true;
441
441
  }
@@ -520,7 +520,14 @@ Item.prototype.run = async function (...params) {
520
520
  * @returns {Promise<any>} 执行结果
521
521
  */
522
522
  Item.prototype.exec = async function (method, ...params) {
523
- if (!this[method]) {
523
+ // 优先从加载的模块中获取方法
524
+ let methodFunc = this._mod && this._mod[method];
525
+ // 如果模块中没有,再检查实例自身
526
+ if (!methodFunc) {
527
+ methodFunc = this[method];
528
+ }
529
+
530
+ if (!methodFunc) {
524
531
  return null;
525
532
  }
526
533
 
@@ -529,9 +536,13 @@ Item.prototype.exec = async function (method, ...params) {
529
536
  try {
530
537
  // 执行前置钩子
531
538
  const beforeMethod = `${method}_before`;
532
- if (this[beforeMethod]) {
539
+ let beforeFunc = this._mod && this._mod[beforeMethod];
540
+ if (!beforeFunc) {
541
+ beforeFunc = this[beforeMethod];
542
+ }
543
+ if (beforeFunc) {
533
544
  try {
534
- result = this[beforeMethod](...params);
545
+ result = beforeFunc.call(this._mod || this, ...params);
535
546
  if (util.types.isPromise(result)) {
536
547
  result = await result;
537
548
  }
@@ -541,14 +552,18 @@ Item.prototype.exec = async function (method, ...params) {
541
552
  }
542
553
 
543
554
  // 执行主方法
544
- const methodResult = this[method](...params);
555
+ const methodResult = methodFunc.call(this._mod || this, ...params);
545
556
  result = util.types.isPromise(methodResult) ? await methodResult : methodResult;
546
557
 
547
558
  // 执行后置钩子
548
559
  const afterMethod = `${method}_after`;
549
- if (this[afterMethod]) {
560
+ let afterFunc = this._mod && this._mod[afterMethod];
561
+ if (!afterFunc) {
562
+ afterFunc = this[afterMethod];
563
+ }
564
+ if (afterFunc) {
550
565
  try {
551
- const afterResult = this[afterMethod](result, ...params);
566
+ const afterResult = afterFunc.call(this._mod || this, result, ...params);
552
567
  if (util.types.isPromise(afterResult)) {
553
568
  const resolvedAfterResult = await afterResult;
554
569
  if (resolvedAfterResult !== undefined) {
@@ -0,0 +1,214 @@
1
+ # 方法清单文档
2
+
3
+ ## 1. index.js - Index类方法
4
+
5
+ ### 构造函数
6
+ - **constructor(scope, dir_base)** - 初始化Index类实例
7
+ - `scope`: 作用域(同时作为检索的后缀名)
8
+ - `dir_base`: 模块目录
9
+
10
+ ### 私有方法
11
+ - **_execute(module, method, params)** - 执行模块方法
12
+ - `module`: 模块对象
13
+ - `method`: 方法名称
14
+ - `params`: 参数数组
15
+ - 返回: Promise<any> - 执行结果
16
+
17
+ ### 公共方法
18
+ - **clear()** - 清除接口缓存
19
+ - **load(dir, cg, file)** - 加载项
20
+ - `dir`: 文件路径
21
+ - `cg`: 配置参数
22
+ - `file`: 配置文件
23
+ - 返回: Promise<Object|null> - 加载的驱动或配置对象
24
+ - **loads(list)** - 加载列表
25
+ - `list`: 文件列表
26
+ - 返回: Promise<void>
27
+ - **sort()** - 排序接口列表
28
+ - **update_before(dir)** - 更新前钩子方法
29
+ - `dir`: 目录路径
30
+ - **update_after(dir)** - 更新后钩子方法
31
+ - `dir`: 目录路径
32
+ - **updateConfigAll(searchPath, accurate)** - 更新所有配置
33
+ - `searchPath`: 检索路径
34
+ - `accurate`: 精准路径标志
35
+ - 返回: Promise<void>
36
+ - **updateConfigHave(dir)** - 更新已有配置文件
37
+ - `dir`: 目录路径
38
+ - 返回: Promise<void>
39
+ - **updateConfig(dir, accurate, clear)** - 更新配置
40
+ - `dir`: 检索目录
41
+ - `accurate`: 精准路径标志
42
+ - `clear`: 是否清除现有配置
43
+ - 返回: Promise<void>
44
+ - **update_script()** - 更新JS脚本
45
+ - 返回: Promise<void>
46
+ - **update_main(dir, accurate, loadJS, clear)** - 更新主逻辑
47
+ - `dir`: 检索路径
48
+ - `accurate`: 精准路径标志
49
+ - `loadJS`: 是否加载JS
50
+ - `clear`: 是否清除现有配置
51
+ - 返回: Promise<void>
52
+ - **update(dir, accurate, loadJS, clear)** - 完整更新流程
53
+ - `dir`: 检索路径
54
+ - `accurate`: 精准路径标志
55
+ - `loadJS`: 是否加载JS
56
+ - `clear`: 是否清除现有配置
57
+ - **get(name)** - 查询配置项
58
+ - `name`: 配置项名称
59
+ - 返回: Object|null - 配置项对象
60
+ - **set(name, cg)** - 设置配置项
61
+ - `name`: 配置项名称
62
+ - `cg`: 配置对象
63
+ - 返回: Boolean - 是否设置成功
64
+ - **save()** - 保存所有配置
65
+ - 返回: Boolean - 是否保存成功
66
+ - **add(config)** - 添加插件
67
+ - `config`: 配置对象
68
+ - 返回: Promise<Object|null> - 新添加的插件对象
69
+ - **del(name)** - 删除插件
70
+ - `name`: 插件名称
71
+ - 返回: Promise<Boolean> - 是否删除成功
72
+ - **load(name)** - 加载插件(重载版本)
73
+ - `name`: 插件名称
74
+ - 返回: Promise<Object|null> - 加载的插件对象
75
+ - **unload(name)** - 卸载插件
76
+ - `name`: 插件名称
77
+ - 返回: Promise<Boolean> - 是否卸载成功
78
+ - **reload(name)** - 重新加载插件
79
+ - `name`: 插件名称
80
+ - 返回: Promise<Object|null> - 重新加载的插件对象
81
+ - **loadFile(file, create)** - 通过文件加载配置
82
+ - `file`: 文件名
83
+ - `create`: 不存在则创建标志
84
+ - 返回: Promise<Object|null|String> - 加载结果
85
+ - **run(name, method, ...params)** - 调用函数
86
+ - `name`: 模块名
87
+ - `method`: 函数名
88
+ - `params`: 参数集合
89
+ - 返回: Promise<any> - 执行结果
90
+ - **exec(name, method, ...params)** - 执行方法
91
+ - `name`: 插件名称
92
+ - `method`: 方法名称
93
+ - `params`: 参数集合
94
+ - 返回: Promise<any> - 执行结果
95
+
96
+ ### 属性
97
+ - **Drive** - 默认驱动类,指向Item类
98
+
99
+ ## 2. item.js - Item类方法
100
+
101
+ ### 构造函数
102
+ - **constructor(dir, dir_base)** - 初始化Item类实例
103
+ - `dir`: 当前目录
104
+ - `dir_base`: 模块目录
105
+
106
+ ### 私有方法
107
+ - **_remove(module)** - 移除模块
108
+ - `module`: 模块对象或路径
109
+
110
+ ### 公共方法
111
+ - **setConfig(config)** - 设置配置
112
+ - `config`: 配置对象
113
+ - **setConfig_after()** - 设置配置后钩子方法
114
+ - **newScript(file)** - 新建脚本文件
115
+ - `file`: 目标文件路径
116
+ - **unloadScript(file)** - 卸载脚本
117
+ - `file`: 脚本文件路径
118
+ - **reloadScript()** - 重新加载脚本
119
+ - **unload()** - 卸载钩子方法
120
+ - **unload_after(remove)** - 卸载之后处理
121
+ - `remove`: 是否删除文件
122
+ - **loadScript(file, name)** - 加载脚本
123
+ - `file`: 文件路径
124
+ - `name`: 函数名
125
+ - 返回: Object|null - 加载的模块对象
126
+ - **newConfig(file)** - 新建配置文件
127
+ - `file`: 目标文件路径
128
+ - **loadFile(file, name)** - 加载配置文件
129
+ - `file`: 文件路径
130
+ - `name`: 配置项名称
131
+ - 返回: Object|null - 配置对象
132
+ - **delDir()** - 删除目录
133
+ - **removeFile()** - 删除配置和脚本文件
134
+ - 返回: String|null - 错误消息
135
+ - **loadConfig(configData, name)** - 载入配置
136
+ - `configData`: 配置对象或配置路径
137
+ - `name`: 配置名称
138
+ - **load_before()** - 加载前处理
139
+ - **load()** - 加载处理
140
+ - **reload()** - 重载配置和脚本
141
+ - **save()** - 保存配置
142
+ - **main(...params)** - 主要执行函数
143
+ - `params`: 参数集合
144
+ - 返回: Promise<any> - 执行结果
145
+ - **run(...params)** - 运行主函数
146
+ - `params`: 参数集合
147
+ - 返回: Promise<any> - 执行结果
148
+ - **exec(method, ...params)** - 调用函数(核心执行方法)
149
+ - `method`: 函数名
150
+ - `params`: 参数集合
151
+ - 返回: Promise<any> - 执行结果
152
+
153
+ ## 3. item.js - 全局方法
154
+
155
+ - **$.require(file, func)** - 增强require函数,支持热更新
156
+ - `file`: 文件路径
157
+ - `func`: 回调函数
158
+ - 返回: Object - 加载的模块
159
+
160
+ - **$.loadJson(file, func)** - 增强JSON加载函数,支持热更新
161
+ - `file`: 文件路径
162
+ - `func`: 回调函数
163
+ - 返回: Object - 解析的JSON对象
164
+
165
+ ## 方法命名规范检查
166
+
167
+ ### 符合规范的方法名(小驼峰)
168
+ - clear
169
+ - load
170
+ - loads
171
+ - sort
172
+ - updateConfigAll
173
+ - updateConfigHave
174
+ - updateConfig
175
+ - get
176
+ - set
177
+ - save
178
+ - add
179
+ - del
180
+ - unload
181
+ - reload
182
+ - loadFile
183
+ - run
184
+ - exec
185
+ - setConfig
186
+ - newScript
187
+ - unloadScript
188
+ - reloadScript
189
+ - loadScript
190
+ - newConfig
191
+ - loadFile
192
+ - delDir
193
+ - removeFile
194
+ - loadConfig
195
+ - main
196
+
197
+ ### 符合规范的时态方法名
198
+ - update_before
199
+ - update_after
200
+ - setConfig_after
201
+ - unload_after
202
+ - load_before
203
+
204
+ ### 需要注意的方法名
205
+ - **updateScript** - 已从update_script修改为符合小驼峰命名规范
206
+ - **update_main** - 保持不变,因为_main属于时态方法命名格式(main表示主逻辑)
207
+
208
+ ## 重复方法名
209
+
210
+ 在index.js中发现两个同名的load方法:
211
+ 1. `load(dir, cg, file)` - 加载项
212
+ 2. `load(name)` - 加载插件
213
+
214
+ 建议重命名其中一个以避免混淆。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mm_machine",
3
- "version": "2.0.5",
3
+ "version": "2.0.7",
4
4
  "description": "这是超级美眉框架机制构建辅助模块,用于快速构建一个机制,支持动态加载、热更新、模块管理等功能,并具有增强的错误处理和现代JavaScript特性支持。",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/test.js CHANGED
@@ -27,6 +27,10 @@ class Engine extends Index {
27
27
  }
28
28
  }
29
29
 
30
+ /**
31
+ * 设置引擎的Drive类
32
+ * @type {Drive}
33
+ */
30
34
  Engine.prototype.Drive = Drive;
31
35
 
32
36
  async function demo() {
@@ -37,42 +41,42 @@ async function demo() {
37
41
  console.log("模块数", engine.list.length);
38
42
  // console.log("模块", engine.list);
39
43
 
40
- await engine.run('demo1', 'init'); // 只有启动状态的插件才会执行
41
- await engine.exec('demo1', 'init'); // 未启动也会执行,并且如果未加载脚本则会自动加载
44
+ await engine.run('test1', 'init'); // 只有启动状态的插件才会执行
45
+ await engine.exec('test1', 'init'); // 未启动也会执行,并且如果未加载脚本则会自动加载
42
46
  await engine.run(null, 'main');
43
47
  await engine.exec(null, 'main');
44
48
 
45
- var ret = await engine.run('demo3', 'main');
46
- console.log("指明回调demo3", ret);
49
+ var ret = await engine.run('test2', 'main');
50
+ console.log("指明回调test2", ret);
47
51
 
48
- var ret = await engine.exec('demo1', 'main');
49
- console.log("指明回调demo1", ret);
52
+ var ret = await engine.exec('test1', 'main');
53
+ console.log("指明回调test1", ret);
50
54
 
51
55
  var i = 0;
52
56
  var timer = setInterval(async () => {
53
- await engine.run('demo1', 'main');
54
- await engine.run('demo2', 'main');
57
+ await engine.run('test1', 'main');
58
+ await engine.run('test2', 'main');
55
59
  i++;
56
60
  if (i == 3) {
57
61
  console.info("→ 重载mod");
58
- await engine.reload("demo1");
62
+ await engine.reload("test1");
59
63
  } else if (i == 5) {
60
64
  console.info("→ 卸载mod");
61
- await engine.unload("demo2");
65
+ await engine.unload("test2");
62
66
  } else if (i == 16) {
63
67
  console.info("→ 卸载并删除mod");
64
- await engine.unload("demo1", true);
68
+ await engine.unload("test1", true);
65
69
  } else if (i == 18) {
66
70
  clearTimeout(timer);
67
71
  }
68
72
  }, 3000);
69
73
 
70
74
  setTimeout(async() => {
71
- var file = "./demo/test1/index.js";
75
+ var file = "./app/test1/index.js";
72
76
  var text = file.loadText();
73
- text = text.replace("123", "1234567");
77
+ text = text.replace("counter = 0", "counter = 100");
74
78
  file.saveText(text);
75
- var ret = await engine.exec("demo1", 'main');
79
+ var ret = await engine.exec("test1", 'main');
76
80
  console.log("这结果", ret);
77
81
  }, 7000)
78
82
 
@@ -88,27 +92,27 @@ async function demo() {
88
92
  console.info("→ 热重载失效");
89
93
  $.mod.config.watch = false;
90
94
  // 失效后再加载的模块修改文件没有变化
91
- var file = "./demo/test1/index.js";
95
+ var file = "./app/test1/index.js";
92
96
  var text = file.loadText();
93
- text = text.replace("1234567", "7654321");
97
+ text = text.replace("counter = 100", "counter = 200");
94
98
  file.saveText(text);
95
- var ret = await engine.exec("demo1", 'main');
99
+ var ret = await engine.exec("test1", 'main');
96
100
  console.log("这结果", ret);
97
101
  }, 16000)
98
102
 
99
103
  var n = 0;
100
104
  var timer_2 = setInterval(async () => {
101
105
  // await engine.update(null, false, false, false);
102
- var ret = await engine.exec('demo1', 'main');
103
- console.info("最后运行demo", ret);
104
- var plug = engine.get("demo1");
106
+ var ret = await engine.exec('test1', 'main');
107
+ console.info("最后运行test1", ret);
108
+ var plug = engine.get("test1");
105
109
  if (plug) {
106
110
  console.log("查看变化1", plug.config);
107
111
  }
108
- var plug = engine.get("demo3");
112
+ var plug = engine.get("test2");
109
113
  if (plug) {
110
114
  var ret = await plug.run();
111
- console.log("查看变化3", plug.config);
115
+ console.log("查看变化2", plug.config);
112
116
  }
113
117
  n++;
114
118
  if (n == 6) {
@@ -1,108 +0,0 @@
1
- var { Index } = require('./index.js');
2
-
3
- // 创建一个测试用的Index子类
4
- class TestIndex extends Index {
5
- constructor() {
6
- super('sys', __dirname);
7
- this.type = 'demo';
8
- }
9
- }
10
-
11
- // 测试函数
12
- async function testDirSearch() {
13
- console.log('开始测试目录搜索逻辑...');
14
-
15
- const index = new TestIndex();
16
- const searchPath = './app/'.fullname(__dirname);
17
-
18
- console.log('搜索路径:', searchPath);
19
- console.log('type:', index.type);
20
- console.log('scope:', index.scope);
21
-
22
- // 计算search_dir
23
- const search_dir = index.scope && index.scope !== $.val?.scope
24
- ? `${index.type}_${index.scope}`
25
- : index.type;
26
-
27
- console.log('search_dir:', search_dir);
28
-
29
- try {
30
- // 测试精准模式(accurate=true)
31
- console.log('\n测试精准模式(accurate=true):');
32
- const list_scope2 = $.dir.getAll(searchPath);
33
- console.log('找到的目录数量:', list_scope2.length);
34
- console.log('找到的目录:', list_scope2.map(d => d.toString()));
35
-
36
- // 测试精准模式下的文件搜索
37
- console.log('\n测试精准模式下的文件搜索:');
38
- for (const dir of list_scope2) {
39
- // 先列出目录中所有文件
40
- console.log(`\n目录 ${dir} 中的所有文件:`);
41
- const all_files = $.file.getAll(dir);
42
- console.log(all_files.map(f => f.toString()));
43
-
44
- // 测试精确文件名搜索(修改后的模式)
45
- console.log(`\n目录 ${dir} 中匹配 ${index.type}.json 的文件:`);
46
- const list_file = $.file.getAll(dir, `${index.type}.json`);
47
- console.log(list_file.map(f => f.toString()));
48
-
49
- // 尝试直接列出demo.json文件
50
- console.log(`\n检查目录 ${dir} 中的 demo.json 文件:`);
51
- const demo_file = `${dir}demo.json`.fullname();
52
- console.log(`文件路径: ${demo_file}`);
53
- console.log(`文件是否存在: ${demo_file.hasFile ? demo_file.hasFile() : '无法检查'}`);
54
-
55
- if (demo_file.hasFile && demo_file.hasFile()) {
56
- try {
57
- const content = demo_file.loadText();
58
- console.log(`文件内容长度:`, content ? content.length : 0);
59
- if (content) {
60
- const json = JSON.parse(content);
61
- console.log(`文件解析成功,是否数组:`, Array.isArray(json));
62
- if (Array.isArray(json)) {
63
- console.log('配置项数量:', json.length);
64
- console.log('配置项名称:', json.map(item => item.name));
65
- } else if (json) {
66
- console.log('配置名称:', json.name);
67
- }
68
- }
69
- } catch (err) {
70
- console.error(`读取文件失败:`, err);
71
- }
72
- }
73
- }
74
-
75
- // 测试非精准模式(accurate=false)
76
- console.log('\n测试非精准模式(accurate=false):');
77
- const list_scope1 = $.dir.getAll(searchPath, search_dir);
78
- console.log('找到的目录数量:', list_scope1.length);
79
- console.log('找到的目录:', list_scope1.map(d => d.toString()));
80
-
81
- // 测试每个目录中的json文件
82
- for (const dir of list_scope1) {
83
- const list_file = $.file.getAll(dir, `*${index.type}.json`);
84
- console.log(`\n目录 ${dir} 中的json文件:`);
85
- console.log(list_file.map(f => f.toString()));
86
- }
87
-
88
- } catch (err) {
89
- console.error('测试失败:', err);
90
- }
91
-
92
- // 直接测试update_config_all方法
93
- console.log('\n直接测试update_config_all方法:');
94
- try {
95
- await index.update_config_all(searchPath, false);
96
- console.log('update_config_all后模块数量:', index.list.length);
97
- if (index.list.length > 0) {
98
- console.log('模块信息:', index.list.map(m => m.config.name));
99
- }
100
- } catch (err) {
101
- console.error('update_config_all失败:', err);
102
- }
103
- }
104
-
105
- // 运行测试
106
- testDirSearch().then(() => {
107
- console.log('\n测试完成');
108
- });