mm_machine 2.1.6 → 2.1.8
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/item.js +133 -45
- package/package.json +3 -2
package/item.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
let util = require('util');
|
|
2
|
+
let { conf } = require('mm_config');
|
|
3
|
+
let Tpl = require('mm_tpl');
|
|
4
|
+
let { HotReload } = require('mm_hot_reload');
|
|
4
5
|
|
|
5
6
|
// 初始化全局对象
|
|
6
7
|
if (typeof global.$ === 'undefined') {
|
|
@@ -11,6 +12,10 @@ if (!$.mod) {
|
|
|
11
12
|
$.mod = new HotReload();
|
|
12
13
|
}
|
|
13
14
|
|
|
15
|
+
if (!$.tpl) {
|
|
16
|
+
$.tpl = new Tpl();
|
|
17
|
+
}
|
|
18
|
+
|
|
14
19
|
/**
|
|
15
20
|
* 增强require函数,支持热更新
|
|
16
21
|
* @param {string} file 文件路径
|
|
@@ -61,7 +66,7 @@ class Item {
|
|
|
61
66
|
// 描述, 用于描述该有什么用的
|
|
62
67
|
description: '',
|
|
63
68
|
// 文件路径, 当调用函数不存在时,会先从文件中加载
|
|
64
|
-
|
|
69
|
+
main: './index.js',
|
|
65
70
|
// 回调函数名 用于决定调用脚本的哪个函数
|
|
66
71
|
func_name: '',
|
|
67
72
|
// 排序
|
|
@@ -103,8 +108,8 @@ Item.prototype.log = function (level, message, ...args) {
|
|
|
103
108
|
Item.prototype.setConfig = function (config) {
|
|
104
109
|
if (!config) return;
|
|
105
110
|
|
|
106
|
-
// 如果
|
|
107
|
-
if (config.
|
|
111
|
+
// 如果main改变,重置加载状态
|
|
112
|
+
if (config.main !== this.config.main) {
|
|
108
113
|
this.complete = false;
|
|
109
114
|
}
|
|
110
115
|
|
|
@@ -124,9 +129,54 @@ Item.prototype.setConfigAfter = function () {
|
|
|
124
129
|
* @param {string} file 目标文件路径
|
|
125
130
|
*/
|
|
126
131
|
Item.prototype.newScript = function (file) {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
132
|
+
this._createScriptFile(file, this.config, this.dir_base);
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* 创建脚本
|
|
138
|
+
* @param {string} file 文件路径
|
|
139
|
+
* @param {object} model 模板数据
|
|
140
|
+
* @param {string} tpl_dir 模板文件路径
|
|
141
|
+
* @returns {boolean} 创建是否成功
|
|
142
|
+
*/
|
|
143
|
+
Item.prototype._createScriptFile = function (file, model = {}, tpl_dir = '') {
|
|
144
|
+
var tpl = this.getScriptTpl(tpl_dir);
|
|
145
|
+
var content = $.tpl.render(tpl, model);
|
|
146
|
+
file.saveText(content);
|
|
147
|
+
return file;
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* 获取脚本模板
|
|
152
|
+
* @param {string} tpl_dir 模板文件路径
|
|
153
|
+
* @returns {string} 脚本模板内容
|
|
154
|
+
*/
|
|
155
|
+
Item.prototype.getScriptTpl = function (tpl_dir = '') {
|
|
156
|
+
var f = './script.tpl.js'.fullname(tpl_dir || this.dir_base);
|
|
157
|
+
if (f.hasFile()) {
|
|
158
|
+
return f.loadText();
|
|
159
|
+
} else {
|
|
160
|
+
return `module.exports = {
|
|
161
|
+
/**
|
|
162
|
+
* 初始化
|
|
163
|
+
*/
|
|
164
|
+
async _init() {
|
|
165
|
+
this.log('debug', \`初始化!\`);
|
|
166
|
+
},
|
|
167
|
+
/**
|
|
168
|
+
* 销毁
|
|
169
|
+
*/
|
|
170
|
+
async _destroy(...args) {
|
|
171
|
+
this.log('debug', \`销毁!\`);
|
|
172
|
+
},
|
|
173
|
+
/**
|
|
174
|
+
* 主要逻辑
|
|
175
|
+
*/
|
|
176
|
+
async main(...args) {
|
|
177
|
+
// 主要代码写在这
|
|
178
|
+
}
|
|
179
|
+
}`;
|
|
130
180
|
}
|
|
131
181
|
};
|
|
132
182
|
|
|
@@ -143,7 +193,7 @@ Item.prototype._remove = function (module) {
|
|
|
143
193
|
$.mod.unload(module);
|
|
144
194
|
} else {
|
|
145
195
|
// 移除模块缓存
|
|
146
|
-
|
|
196
|
+
let filename = require.resolve(module);
|
|
147
197
|
if (require.cache[filename]) {
|
|
148
198
|
require.cache[filename] = null;
|
|
149
199
|
delete require.cache[filename];
|
|
@@ -161,9 +211,9 @@ Item.prototype._remove = function (module) {
|
|
|
161
211
|
Item.prototype.unloadScript = function (file) {
|
|
162
212
|
let target_file = file;
|
|
163
213
|
if (!target_file) {
|
|
164
|
-
|
|
165
|
-
if (
|
|
166
|
-
target_file =
|
|
214
|
+
let main = this.config.main;
|
|
215
|
+
if (main) {
|
|
216
|
+
target_file = main.fullname(this.dir);
|
|
167
217
|
}
|
|
168
218
|
}
|
|
169
219
|
|
|
@@ -208,13 +258,13 @@ Item.prototype.unloadAfter = async function (remove) {
|
|
|
208
258
|
* @returns {object | null} 返回加载的模块对象
|
|
209
259
|
*/
|
|
210
260
|
Item.prototype.loadScript = function (file, name = '') {
|
|
211
|
-
|
|
261
|
+
let target_file = this._getScriptFile(file);
|
|
212
262
|
if (!target_file) return null;
|
|
213
263
|
|
|
214
|
-
|
|
264
|
+
let target_name = this._getScriptName(name);
|
|
215
265
|
|
|
216
266
|
try {
|
|
217
|
-
|
|
267
|
+
let cs = this._loadScript(target_file, target_name);
|
|
218
268
|
this._setMainMethod(cs, target_name);
|
|
219
269
|
return cs;
|
|
220
270
|
} catch (err) {
|
|
@@ -231,10 +281,10 @@ Item.prototype.loadScript = function (file, name = '') {
|
|
|
231
281
|
Item.prototype._getScriptFile = function (file) {
|
|
232
282
|
if (file) return file;
|
|
233
283
|
|
|
234
|
-
|
|
235
|
-
if (!
|
|
284
|
+
let main = this.config.main;
|
|
285
|
+
if (!main) return null;
|
|
236
286
|
|
|
237
|
-
|
|
287
|
+
let target_file = main.fullname(this.dir);
|
|
238
288
|
if (!target_file.hasFile()) {
|
|
239
289
|
this.newScript(target_file);
|
|
240
290
|
}
|
|
@@ -286,8 +336,46 @@ Item.prototype._setMainMethod = function (module, name) {
|
|
|
286
336
|
* @param {string} file 目标文件路径
|
|
287
337
|
*/
|
|
288
338
|
Item.prototype.newConfig = function (file) {
|
|
289
|
-
|
|
290
|
-
|
|
339
|
+
if (!this.config.name) {
|
|
340
|
+
this.config.name = file.dirname().basename();
|
|
341
|
+
}
|
|
342
|
+
this._createConfigFile(file, this.config, this.dir_base);
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
Item.prototype._createConfigFile = function (file, model = {}, tpl_dir = '') {
|
|
346
|
+
var tpl = this.getConfigTpl(tpl_dir);
|
|
347
|
+
var content = $.tpl.render(tpl, model);
|
|
348
|
+
file.saveText(content);
|
|
349
|
+
return file;
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* 获取配置模板
|
|
354
|
+
* @param {string} tpl_dir 模板文件路径
|
|
355
|
+
* @returns {string} 配置模板内容
|
|
356
|
+
*/
|
|
357
|
+
Item.prototype.getConfigTpl = function (tpl_dir = '') {
|
|
358
|
+
var f = './config.tpl.json'.fullname(tpl_dir || this.dir_base);
|
|
359
|
+
if (f.hasFile()) {
|
|
360
|
+
return f.loadText();
|
|
361
|
+
} else {
|
|
362
|
+
return `{
|
|
363
|
+
// 模块名称,必填
|
|
364
|
+
'name': '\${name}',
|
|
365
|
+
// 模块标题,可选,默认"示例标题"
|
|
366
|
+
'title': '\${title || "示例标题"}',
|
|
367
|
+
// 模块描述,可选,默认"示例描述"
|
|
368
|
+
'description': '\${description || "示例描述"}',
|
|
369
|
+
// 主脚本文件路径,可选,默认"./index.js"
|
|
370
|
+
'main': '\${main || "./index.js"}',
|
|
371
|
+
// 模块作用域,可选,默认"server"
|
|
372
|
+
'scope': '\${scope || "server"}',
|
|
373
|
+
// 模块状态,可选,默认1
|
|
374
|
+
'state': \${state || 1},
|
|
375
|
+
// 模块排序,可选,默认100
|
|
376
|
+
'sort': \${sort || 100}
|
|
377
|
+
}`;
|
|
378
|
+
}
|
|
291
379
|
};
|
|
292
380
|
|
|
293
381
|
/**
|
|
@@ -298,7 +386,7 @@ Item.prototype.newConfig = function (file) {
|
|
|
298
386
|
*/
|
|
299
387
|
Item.prototype.loadFile = function (file, name) {
|
|
300
388
|
try {
|
|
301
|
-
|
|
389
|
+
let full_path = file.fullname(this.dir);
|
|
302
390
|
let text = full_path.loadText();
|
|
303
391
|
|
|
304
392
|
// 如果文件不存在,创建新的配置文件
|
|
@@ -309,8 +397,8 @@ Item.prototype.loadFile = function (file, name) {
|
|
|
309
397
|
|
|
310
398
|
if (!text) return null;
|
|
311
399
|
|
|
312
|
-
|
|
313
|
-
|
|
400
|
+
let config = this._loadHotReload(full_path);
|
|
401
|
+
let final_config = this._findConfigByName(config, name);
|
|
314
402
|
|
|
315
403
|
// 更新目录和文件名引用
|
|
316
404
|
this.dir = full_path.dirname();
|
|
@@ -378,8 +466,8 @@ Item.prototype._reloadIfNeeded = function () {
|
|
|
378
466
|
* 删除目录
|
|
379
467
|
*/
|
|
380
468
|
Item.prototype.delDir = function () {
|
|
381
|
-
|
|
382
|
-
if (
|
|
469
|
+
let main = this.config.main;
|
|
470
|
+
if (main && $.dir && $.dir.del) {
|
|
383
471
|
$.dir.del(this.dir);
|
|
384
472
|
}
|
|
385
473
|
};
|
|
@@ -389,8 +477,8 @@ Item.prototype.delDir = function () {
|
|
|
389
477
|
* @returns {string | null} 错误消息,如果没有错误则返回null
|
|
390
478
|
*/
|
|
391
479
|
Item.prototype.removeFile = function () {
|
|
392
|
-
|
|
393
|
-
|
|
480
|
+
let name = this.config.name;
|
|
481
|
+
let file = this.filename;
|
|
394
482
|
|
|
395
483
|
let error_message = null;
|
|
396
484
|
try {
|
|
@@ -415,13 +503,13 @@ Item.prototype.removeFile = function () {
|
|
|
415
503
|
* @returns {string | null} 错误消息
|
|
416
504
|
*/
|
|
417
505
|
Item.prototype._removeConfigFile = function (file, name) {
|
|
418
|
-
|
|
506
|
+
let text = file.loadText();
|
|
419
507
|
if (!text) {
|
|
420
508
|
this.delDir();
|
|
421
509
|
return null;
|
|
422
510
|
}
|
|
423
511
|
|
|
424
|
-
|
|
512
|
+
let config = text.toJson();
|
|
425
513
|
if (Array.isArray(config)) {
|
|
426
514
|
return this._removeArrayItem(file, config, name);
|
|
427
515
|
}
|
|
@@ -438,7 +526,7 @@ Item.prototype._removeConfigFile = function (file, name) {
|
|
|
438
526
|
* @returns {string | null} 错误消息
|
|
439
527
|
*/
|
|
440
528
|
Item.prototype._removeArrayItem = function (file, config, name) {
|
|
441
|
-
|
|
529
|
+
let index = config.findIndex((item) => item.name === name);
|
|
442
530
|
if (index === -1) return null;
|
|
443
531
|
|
|
444
532
|
this.delDir();
|
|
@@ -483,7 +571,7 @@ Item.prototype.loadConfig = async function (config_data, name) {
|
|
|
483
571
|
*/
|
|
484
572
|
Item.prototype.loadBefore = async function () {
|
|
485
573
|
try {
|
|
486
|
-
|
|
574
|
+
let module = this.loadScript();
|
|
487
575
|
if (module) {
|
|
488
576
|
this.complete = true;
|
|
489
577
|
}
|
|
@@ -515,15 +603,15 @@ Item.prototype.save = function () {
|
|
|
515
603
|
try {
|
|
516
604
|
if (!this.filename) return;
|
|
517
605
|
|
|
518
|
-
|
|
519
|
-
|
|
606
|
+
let full_path = this.filename.fullname(this.dir);
|
|
607
|
+
let text = full_path.loadText();
|
|
520
608
|
|
|
521
609
|
if (text && text.trim().startsWith('[')) {
|
|
522
610
|
// 数组格式配置
|
|
523
|
-
|
|
611
|
+
let config_array = text.toJson();
|
|
524
612
|
if (Array.isArray(config_array)) {
|
|
525
613
|
// 查找并更新现有配置项
|
|
526
|
-
|
|
614
|
+
let existing_index = config_array.findIndex((item) => item.name === this.config.name);
|
|
527
615
|
if (existing_index !== -1) {
|
|
528
616
|
config_array[existing_index] = this.config;
|
|
529
617
|
} else {
|
|
@@ -568,7 +656,7 @@ Item.prototype.run = async function (...params) {
|
|
|
568
656
|
* @returns {Promise<any>} 执行结果
|
|
569
657
|
*/
|
|
570
658
|
Item.prototype.exec = async function (method, ...params) {
|
|
571
|
-
|
|
659
|
+
let method_func = this._getMethod(method);
|
|
572
660
|
if (!method_func) return null;
|
|
573
661
|
|
|
574
662
|
let result;
|
|
@@ -605,8 +693,8 @@ Item.prototype._getMethod = function (method) {
|
|
|
605
693
|
* @returns {Promise<any>} 前置钩子结果
|
|
606
694
|
*/
|
|
607
695
|
Item.prototype._execBefore = async function (method, params) {
|
|
608
|
-
|
|
609
|
-
|
|
696
|
+
let before_method = `${method}Before`;
|
|
697
|
+
let before_func = this._getMethod(before_method);
|
|
610
698
|
|
|
611
699
|
if (!before_func) return undefined;
|
|
612
700
|
|
|
@@ -630,8 +718,8 @@ Item.prototype._execBefore = async function (method, params) {
|
|
|
630
718
|
* @returns {Promise<any>} 主方法结果
|
|
631
719
|
*/
|
|
632
720
|
Item.prototype._execMain = async function (method_func, params, before_result) {
|
|
633
|
-
|
|
634
|
-
|
|
721
|
+
let method_result = method_func.call(this._mod || this, ...params);
|
|
722
|
+
let result = util.types.isPromise(method_result) ? await method_result : method_result;
|
|
635
723
|
return result;
|
|
636
724
|
};
|
|
637
725
|
|
|
@@ -643,16 +731,16 @@ Item.prototype._execMain = async function (method_func, params, before_result) {
|
|
|
643
731
|
* @returns {Promise<any>} 后置钩子结果
|
|
644
732
|
*/
|
|
645
733
|
Item.prototype._execAfter = async function (method, params, main_result) {
|
|
646
|
-
|
|
647
|
-
|
|
734
|
+
let after_method = `${method}After`;
|
|
735
|
+
let after_func = this._getMethod(after_method);
|
|
648
736
|
|
|
649
737
|
if (!after_func) return main_result;
|
|
650
738
|
|
|
651
739
|
try {
|
|
652
|
-
|
|
740
|
+
let after_result = after_func.call(this._mod || this, main_result, ...params);
|
|
653
741
|
|
|
654
742
|
if (util.types.isPromise(after_result)) {
|
|
655
|
-
|
|
743
|
+
let resolved_result = await after_result;
|
|
656
744
|
return resolved_result !== undefined ? resolved_result : main_result;
|
|
657
745
|
}
|
|
658
746
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mm_machine",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.8",
|
|
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": {
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
],
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"mm_config": "^2.2.3",
|
|
35
|
-
"mm_hot_reload": "^1.2.0"
|
|
35
|
+
"mm_hot_reload": "^1.2.0",
|
|
36
|
+
"mm_tpl": "^2.4.7"
|
|
36
37
|
}
|
|
37
38
|
}
|