mm_machine 2.2.1 → 2.2.3
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/index.js +43 -42
- package/item.js +33 -25
- package/package.json +6 -1
package/index.js
CHANGED
|
@@ -93,7 +93,7 @@ Index.prototype._exec = async function (module, method, params = []) {
|
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
// 执行方法
|
|
96
|
-
|
|
96
|
+
let ret = await module.exec(method, ...params);
|
|
97
97
|
|
|
98
98
|
// 根据模式决定是否重载
|
|
99
99
|
if (this.mode >= 4) {
|
|
@@ -105,7 +105,7 @@ Index.prototype._exec = async function (module, method, params = []) {
|
|
|
105
105
|
$.log.error(`[${this.type}] 执行模块方法失败: `, err);
|
|
106
106
|
return null;
|
|
107
107
|
}
|
|
108
|
-
}
|
|
108
|
+
};
|
|
109
109
|
|
|
110
110
|
/**
|
|
111
111
|
* 加载项
|
|
@@ -114,7 +114,7 @@ Index.prototype._exec = async function (module, method, params = []) {
|
|
|
114
114
|
* @param {string} file 配置文件
|
|
115
115
|
* @returns {Promise<object | null>} 加载的驱动或配置对象
|
|
116
116
|
*/
|
|
117
|
-
Index.prototype.
|
|
117
|
+
Index.prototype.loadDrive = async function (dir, cg, file) {
|
|
118
118
|
if (!dir || !file) {
|
|
119
119
|
$.log.error(`[${this.type}] load: 缺少必要参数`);
|
|
120
120
|
return null;
|
|
@@ -135,7 +135,7 @@ Index.prototype.loadItem = async function (dir, cg, file) {
|
|
|
135
135
|
} else {
|
|
136
136
|
let json = file.loadJson();
|
|
137
137
|
if (!json) {
|
|
138
|
-
|
|
138
|
+
let fl = './config.tpl.json'.fullname(this.dir_base);
|
|
139
139
|
if (fl.hasFile()) {
|
|
140
140
|
fl.copyFile(file);
|
|
141
141
|
json = file.loadJson();
|
|
@@ -176,8 +176,8 @@ Index.prototype.loads = async function (list) {
|
|
|
176
176
|
*/
|
|
177
177
|
Index.prototype.sort = function () {
|
|
178
178
|
this.list.sort((o1, o2) => {
|
|
179
|
-
|
|
180
|
-
|
|
179
|
+
let p1 = o1.config?.[this.sort_key] || 0;
|
|
180
|
+
let p2 = o2.config?.[this.sort_key] || 0;
|
|
181
181
|
return p2 - p1;
|
|
182
182
|
});
|
|
183
183
|
};
|
|
@@ -203,7 +203,7 @@ Index.prototype.updateAfter = async function (dir_path) {
|
|
|
203
203
|
* @param {string} search_path 检索路径
|
|
204
204
|
* @returns {string} 规范化后的路径
|
|
205
205
|
*/
|
|
206
|
-
Index.prototype.
|
|
206
|
+
Index.prototype._searchPath = function (search_path) {
|
|
207
207
|
if (!search_path) {
|
|
208
208
|
return './app/';
|
|
209
209
|
}
|
|
@@ -216,7 +216,7 @@ Index.prototype._normalizeSearchPath = function (search_path) {
|
|
|
216
216
|
* @param {string} norm_path 规范化路径
|
|
217
217
|
* @returns {Array} 目录列表
|
|
218
218
|
*/
|
|
219
|
-
Index.prototype.
|
|
219
|
+
Index.prototype._getDirList = function (norm_path) {
|
|
220
220
|
try {
|
|
221
221
|
// 使用精准模式总是获取所有目录
|
|
222
222
|
// 这样可以确保找到test1和test2目录
|
|
@@ -232,15 +232,15 @@ Index.prototype._getDirectoryList = function (norm_path) {
|
|
|
232
232
|
* @param {string} dir 目录路径
|
|
233
233
|
* @returns {Promise<void>}
|
|
234
234
|
*/
|
|
235
|
-
Index.prototype.
|
|
235
|
+
Index.prototype._runDirConfig = async function (dir) {
|
|
236
236
|
// 直接检查并加载demo.json文件
|
|
237
|
-
|
|
237
|
+
let config_file = `./${this.type}.json`.fullname(dir);
|
|
238
238
|
if (config_file && config_file.hasFile && config_file.hasFile()) {
|
|
239
239
|
await this.loadFile(config_file, true);
|
|
240
240
|
}
|
|
241
241
|
|
|
242
242
|
// 同时也检查config_demo.json文件
|
|
243
|
-
|
|
243
|
+
let config_file2 = `./config_${this.type}.json`.fullname(dir);
|
|
244
244
|
if (config_file2 && config_file2.hasFile && config_file2.hasFile()) {
|
|
245
245
|
await this.loadFile(config_file2, true);
|
|
246
246
|
}
|
|
@@ -255,15 +255,15 @@ Index.prototype._processDirectoryConfig = async function (dir) {
|
|
|
255
255
|
Index.prototype.updateConfigAll = async function (search_path, accurate) {
|
|
256
256
|
try {
|
|
257
257
|
// 规范化路径
|
|
258
|
-
|
|
258
|
+
let norm_path = this._searchPath(search_path);
|
|
259
259
|
|
|
260
260
|
// 获取目录列表
|
|
261
|
-
|
|
261
|
+
let list_scope = this._getDirList(norm_path);
|
|
262
262
|
|
|
263
263
|
// 使用函数式编程处理目录
|
|
264
264
|
await list_scope.reduce(async (prev_promise, dir) => {
|
|
265
265
|
await prev_promise;
|
|
266
|
-
return this.
|
|
266
|
+
return this._runDirConfig(dir);
|
|
267
267
|
}, Promise.resolve());
|
|
268
268
|
} catch (err) {
|
|
269
269
|
$.log.error(`[${this.type}] 更新所有配置失败: `, err);
|
|
@@ -276,7 +276,7 @@ Index.prototype.updateConfigAll = async function (search_path, accurate) {
|
|
|
276
276
|
* @returns {Promise<void>}
|
|
277
277
|
*/
|
|
278
278
|
Index.prototype.updateConfigHave = async function (dir_path) {
|
|
279
|
-
|
|
279
|
+
let list = this.list;
|
|
280
280
|
await list.reduce(async (prev_promise, o) => {
|
|
281
281
|
await prev_promise;
|
|
282
282
|
return this._updateSingleConfig(o);
|
|
@@ -288,14 +288,14 @@ Index.prototype.updateConfigHave = async function (dir_path) {
|
|
|
288
288
|
* @param {object} o 配置对象
|
|
289
289
|
*/
|
|
290
290
|
Index.prototype._updateSingleConfig = async function (o) {
|
|
291
|
-
|
|
291
|
+
let file = o.filename;
|
|
292
292
|
if (!file) return;
|
|
293
293
|
|
|
294
294
|
try {
|
|
295
|
-
|
|
295
|
+
let config = file.loadJson();
|
|
296
296
|
if (!config) return;
|
|
297
297
|
|
|
298
|
-
|
|
298
|
+
let target_config = this._findConfig(config, o.config.name);
|
|
299
299
|
if (target_config) {
|
|
300
300
|
await o.exec('setConfig', target_config);
|
|
301
301
|
}
|
|
@@ -344,7 +344,7 @@ Index.prototype.updateConfig = async function (dir, accurate = false, clear = fa
|
|
|
344
344
|
* @returns {Promise<void>}
|
|
345
345
|
*/
|
|
346
346
|
Index.prototype.updateScript = async function () {
|
|
347
|
-
|
|
347
|
+
let list = this.list;
|
|
348
348
|
await list.reduce(async (prev_promise, o) => {
|
|
349
349
|
await prev_promise;
|
|
350
350
|
if (o.config?.state === 1) {
|
|
@@ -400,7 +400,7 @@ Index.prototype.get = function (name) {
|
|
|
400
400
|
Index.prototype.set = function (name, cg) {
|
|
401
401
|
if (!name || !cg) return false;
|
|
402
402
|
|
|
403
|
-
|
|
403
|
+
let item = this.get(name);
|
|
404
404
|
if (item) {
|
|
405
405
|
// 使用Object.assign合并属性
|
|
406
406
|
Object.assign(item.config, cg);
|
|
@@ -414,7 +414,7 @@ Index.prototype.set = function (name, cg) {
|
|
|
414
414
|
* @returns {boolean} 是否保存成功
|
|
415
415
|
*/
|
|
416
416
|
Index.prototype.save = async function () {
|
|
417
|
-
|
|
417
|
+
let list = this.list;
|
|
418
418
|
await list.reduce(async (prev_promise, o) => {
|
|
419
419
|
await prev_promise;
|
|
420
420
|
if (o.config?.state === 1) {
|
|
@@ -436,7 +436,7 @@ Index.prototype.add = async function (config) {
|
|
|
436
436
|
|
|
437
437
|
try {
|
|
438
438
|
// 检查是否已存在
|
|
439
|
-
|
|
439
|
+
let existing = this.get(config.name);
|
|
440
440
|
if (existing) {
|
|
441
441
|
$.log.warn(`插件 ${config.name} 已存在`);
|
|
442
442
|
return existing;
|
|
@@ -460,11 +460,11 @@ Index.prototype.add = async function (config) {
|
|
|
460
460
|
Index.prototype.del = async function (name) {
|
|
461
461
|
if (!name) return false;
|
|
462
462
|
|
|
463
|
-
|
|
463
|
+
let index = this.list.findIndex((item) => item.config?.name === name);
|
|
464
464
|
if (index === -1) return false;
|
|
465
465
|
|
|
466
466
|
try {
|
|
467
|
-
|
|
467
|
+
let item = this.list[index];
|
|
468
468
|
await item.exec('unload');
|
|
469
469
|
this.list.splice(index, 1);
|
|
470
470
|
return true;
|
|
@@ -482,7 +482,7 @@ Index.prototype.del = async function (name) {
|
|
|
482
482
|
Index.prototype.load = async function (name) {
|
|
483
483
|
if (!name) return null;
|
|
484
484
|
|
|
485
|
-
|
|
485
|
+
let item = this.get(name);
|
|
486
486
|
if (!item) return null;
|
|
487
487
|
|
|
488
488
|
try {
|
|
@@ -504,7 +504,7 @@ Index.prototype.load = async function (name) {
|
|
|
504
504
|
Index.prototype.unload = async function (name) {
|
|
505
505
|
if (!name) return false;
|
|
506
506
|
|
|
507
|
-
|
|
507
|
+
let item = this.get(name);
|
|
508
508
|
if (!item) return false;
|
|
509
509
|
|
|
510
510
|
try {
|
|
@@ -524,7 +524,7 @@ Index.prototype.unload = async function (name) {
|
|
|
524
524
|
Index.prototype.reload = async function (name) {
|
|
525
525
|
if (!name) return null;
|
|
526
526
|
|
|
527
|
-
|
|
527
|
+
let item = this.get(name);
|
|
528
528
|
if (!item) return null;
|
|
529
529
|
|
|
530
530
|
try {
|
|
@@ -544,22 +544,22 @@ Index.prototype.reload = async function (name) {
|
|
|
544
544
|
*/
|
|
545
545
|
Index.prototype.loadFile = async function (file, create = false) {
|
|
546
546
|
try {
|
|
547
|
-
|
|
547
|
+
let dir = file.dirname();
|
|
548
548
|
// 载入文件
|
|
549
|
-
|
|
549
|
+
let obj = file.loadJson();
|
|
550
550
|
if (obj) {
|
|
551
551
|
if (Array.isArray(obj)) {
|
|
552
552
|
// 使用函数式编程处理数组
|
|
553
553
|
await obj.reduce(async (prev_promise, o) => {
|
|
554
554
|
await prev_promise;
|
|
555
555
|
// 实例化一个驱动
|
|
556
|
-
return this.
|
|
556
|
+
return this.loadDrive(dir, o, file);
|
|
557
557
|
}, Promise.resolve());
|
|
558
558
|
} else {
|
|
559
|
-
return await this.
|
|
559
|
+
return await this.loadDrive(dir, null, file);
|
|
560
560
|
}
|
|
561
561
|
} else if (create) {
|
|
562
|
-
return await this.
|
|
562
|
+
return await this.loadDrive(dir, null, file);
|
|
563
563
|
} else {
|
|
564
564
|
return `${file}文件不存在`;
|
|
565
565
|
}
|
|
@@ -579,22 +579,23 @@ Index.prototype.loadFile = async function (file, create = false) {
|
|
|
579
579
|
*/
|
|
580
580
|
Index.prototype.run = async function (name, method, ...params) {
|
|
581
581
|
if (name) {
|
|
582
|
-
|
|
582
|
+
let module = await this.get(name);
|
|
583
583
|
if (module && module.config?.state === 1) {
|
|
584
584
|
return await this._exec(module, method, params);
|
|
585
585
|
}
|
|
586
586
|
return null;
|
|
587
587
|
} else if (name === null) {
|
|
588
588
|
let result = null;
|
|
589
|
-
//
|
|
590
|
-
|
|
589
|
+
// 修复:使用for循环替代some,正确处理异步迭代
|
|
590
|
+
for (let module of this.list) {
|
|
591
591
|
if (module.config?.state === 1) {
|
|
592
592
|
result = await this._exec(module, method, params);
|
|
593
593
|
// 如果结果不为空且有结束标志,则停止迭代
|
|
594
|
-
|
|
594
|
+
if (result && module.config?.end) {
|
|
595
|
+
break;
|
|
596
|
+
}
|
|
595
597
|
}
|
|
596
|
-
|
|
597
|
-
});
|
|
598
|
+
}
|
|
598
599
|
return result;
|
|
599
600
|
}
|
|
600
601
|
return null;
|
|
@@ -609,7 +610,7 @@ Index.prototype.run = async function (name, method, ...params) {
|
|
|
609
610
|
*/
|
|
610
611
|
Index.prototype.exec = async function (name, method, ...params) {
|
|
611
612
|
if (name) {
|
|
612
|
-
|
|
613
|
+
let module = await this.get(name);
|
|
613
614
|
if (module) {
|
|
614
615
|
return await this._exec(module, method, params);
|
|
615
616
|
}
|
|
@@ -623,9 +624,9 @@ Index.prototype.exec = async function (name, method, ...params) {
|
|
|
623
624
|
if (result && module.config?.end) {
|
|
624
625
|
return;
|
|
625
626
|
}
|
|
626
|
-
|
|
627
|
-
if (
|
|
628
|
-
result =
|
|
627
|
+
let current = await this._exec(module, method, params);
|
|
628
|
+
if (current) {
|
|
629
|
+
result = current;
|
|
629
630
|
}
|
|
630
631
|
}, Promise.resolve());
|
|
631
632
|
return result;
|
package/item.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
let util = require('util');
|
|
2
2
|
let { conf } = require('mm_config');
|
|
3
|
-
|
|
3
|
+
const Tpl = require('mm_tpl');
|
|
4
4
|
let { HotReload } = require('mm_hot_reload');
|
|
5
5
|
|
|
6
6
|
// 初始化全局对象
|
|
@@ -103,7 +103,6 @@ Item.prototype.log = function (level, message, ...args) {
|
|
|
103
103
|
/**
|
|
104
104
|
* 设置配置
|
|
105
105
|
* @param {object} config 配置对象
|
|
106
|
-
* @returns {Promise<void>}
|
|
107
106
|
*/
|
|
108
107
|
Item.prototype.setConfig = function (config) {
|
|
109
108
|
if (!config) return;
|
|
@@ -352,6 +351,13 @@ Item.prototype.newConfig = function (file) {
|
|
|
352
351
|
this._createConfigFile(file, this.config, this.dir_base);
|
|
353
352
|
};
|
|
354
353
|
|
|
354
|
+
/**
|
|
355
|
+
* 创建配置文件
|
|
356
|
+
* @param {string} file 目标文件路径
|
|
357
|
+
* @param {object} model 配置模型对象
|
|
358
|
+
* @param {string} tpl_dir 模板文件路径
|
|
359
|
+
* @returns {string} 配置文件内容
|
|
360
|
+
*/
|
|
355
361
|
Item.prototype._createConfigFile = function (file, model = {}, tpl_dir = '') {
|
|
356
362
|
var tpl = this.getConfigTpl(tpl_dir);
|
|
357
363
|
var content = $.tpl.render(tpl, model);
|
|
@@ -521,7 +527,7 @@ Item.prototype._removeConfigFile = function (file, name) {
|
|
|
521
527
|
|
|
522
528
|
let config = text.toJson();
|
|
523
529
|
if (Array.isArray(config)) {
|
|
524
|
-
return this.
|
|
530
|
+
return this._removeArray(file, config, name);
|
|
525
531
|
}
|
|
526
532
|
|
|
527
533
|
this.delDir();
|
|
@@ -535,7 +541,7 @@ Item.prototype._removeConfigFile = function (file, name) {
|
|
|
535
541
|
* @param {string} name 配置名称
|
|
536
542
|
* @returns {string | null} 错误消息
|
|
537
543
|
*/
|
|
538
|
-
Item.prototype.
|
|
544
|
+
Item.prototype._removeArray = function (file, config, name) {
|
|
539
545
|
let index = config.findIndex((item) => item.name === name);
|
|
540
546
|
if (index === -1) return null;
|
|
541
547
|
|
|
@@ -627,17 +633,17 @@ Item.prototype.save = function () {
|
|
|
627
633
|
|
|
628
634
|
if (text && text.trim().startsWith('[')) {
|
|
629
635
|
// 数组格式配置
|
|
630
|
-
let
|
|
631
|
-
if (Array.isArray(
|
|
636
|
+
let config = text.toJson();
|
|
637
|
+
if (Array.isArray(config)) {
|
|
632
638
|
// 查找并更新现有配置项
|
|
633
|
-
let
|
|
634
|
-
if (
|
|
635
|
-
|
|
639
|
+
let index = config.findIndex((item) => item.name === this.config.name);
|
|
640
|
+
if (index !== -1) {
|
|
641
|
+
config[index] = this.config;
|
|
636
642
|
} else {
|
|
637
643
|
// 如果不存在,添加新配置项
|
|
638
|
-
|
|
644
|
+
config.push(this.config);
|
|
639
645
|
}
|
|
640
|
-
full_path.saveText(JSON.stringify(
|
|
646
|
+
full_path.saveText(JSON.stringify(config, null, 4));
|
|
641
647
|
return;
|
|
642
648
|
}
|
|
643
649
|
}
|
|
@@ -733,40 +739,42 @@ Item.prototype._execBefore = async function (method, params) {
|
|
|
733
739
|
* 执行主方法
|
|
734
740
|
* @param {Function} method_func 方法函数
|
|
735
741
|
* @param {Array} params 参数
|
|
736
|
-
* @param {any}
|
|
742
|
+
* @param {any} result 前置钩子结果
|
|
737
743
|
* @returns {Promise<any>} 主方法结果
|
|
738
744
|
*/
|
|
739
|
-
Item.prototype._execMain = async function (method_func, params,
|
|
745
|
+
Item.prototype._execMain = async function (method_func, params, result) {
|
|
740
746
|
let method_result = method_func.call(this._mod || this, ...params);
|
|
741
|
-
|
|
742
|
-
|
|
747
|
+
if (util.types.isPromise(method_result)) {
|
|
748
|
+
method_result = await method_result;
|
|
749
|
+
}
|
|
750
|
+
// 修复:如果主方法返回undefined,则使用前置钩子的结果
|
|
751
|
+
return method_result !== undefined ? method_result : result;
|
|
743
752
|
};
|
|
744
753
|
|
|
745
754
|
/**
|
|
746
755
|
* 执行后置钩子
|
|
747
756
|
* @param {string} method 方法名
|
|
748
757
|
* @param {Array} params 参数
|
|
749
|
-
* @param {any}
|
|
758
|
+
* @param {any} result 主方法结果
|
|
750
759
|
* @returns {Promise<any>} 后置钩子结果
|
|
751
760
|
*/
|
|
752
|
-
Item.prototype._execAfter = async function (method, params,
|
|
761
|
+
Item.prototype._execAfter = async function (method, params, result) {
|
|
753
762
|
let after_method = `${method}After`;
|
|
754
763
|
let after_func = this._getMethod(after_method);
|
|
755
764
|
|
|
756
|
-
if (!after_func) return
|
|
765
|
+
if (!after_func) return result;
|
|
757
766
|
|
|
758
767
|
try {
|
|
759
|
-
let
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
return resolved_result !== undefined ? resolved_result : main_result;
|
|
768
|
+
let after = after_func.call(this._mod || this, result, ...params);
|
|
769
|
+
if (util.types.isPromise(after)) {
|
|
770
|
+
let resolved = await after;
|
|
771
|
+
return resolved !== undefined ? resolved : result;
|
|
764
772
|
}
|
|
765
773
|
|
|
766
|
-
return
|
|
774
|
+
return after !== undefined ? after : result;
|
|
767
775
|
} catch (err) {
|
|
768
776
|
this.log('error', `执行后置钩子 ${after_method} 失败: `, err);
|
|
769
|
-
return
|
|
777
|
+
return result;
|
|
770
778
|
}
|
|
771
779
|
};
|
|
772
780
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mm_machine",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.3",
|
|
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": {
|
|
@@ -34,5 +34,10 @@
|
|
|
34
34
|
"mm_config": "^2.2.5",
|
|
35
35
|
"mm_hot_reload": "^1.2.0",
|
|
36
36
|
"mm_tpl": "^2.4.7"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"eslint": "^9.39.2",
|
|
40
|
+
"eslint-plugin-jsdoc": "^62.5.0",
|
|
41
|
+
"mm_eslint": "^1.6.6"
|
|
37
42
|
}
|
|
38
43
|
}
|