mm_machine 2.3.4 → 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.
- package/drive.js +112 -34
- package/index.js +42 -3
- package/mod.js +13 -8
- 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.
|
|
176
|
-
var f = './script.tpl.js'.fullname(
|
|
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',
|
|
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.
|
|
420
|
+
var tpl = this._getConfigTpl();
|
|
343
421
|
var content = $.tpl.render(tpl, this.config);
|
|
344
|
-
|
|
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.
|
|
354
|
-
var f = './config.tpl.json'.fullname(
|
|
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
|
-
|
|
374
|
-
|
|
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,
|
|
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,
|
|
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
|
@@ -45,6 +45,11 @@ class Manager extends Mod {
|
|
|
45
45
|
* @type {string}
|
|
46
46
|
*/
|
|
47
47
|
dir: './ai/manager'.fullname(),
|
|
48
|
+
/**
|
|
49
|
+
* 搜索模式 dir按目录搜索 | file按文件名搜索
|
|
50
|
+
* @type {string}
|
|
51
|
+
*/
|
|
52
|
+
search_way: 'file',
|
|
48
53
|
/**
|
|
49
54
|
* 类型 script脚本 | json配置 | drive驱动
|
|
50
55
|
* @type {string}
|
|
@@ -71,7 +76,7 @@ class Manager extends Mod {
|
|
|
71
76
|
*/
|
|
72
77
|
sort_key: 'sort',
|
|
73
78
|
/**
|
|
74
|
-
*
|
|
79
|
+
* 作用域
|
|
75
80
|
* @type {string}
|
|
76
81
|
*/
|
|
77
82
|
scope: ($.val && $.val.scope) ? $.val.scope + '' : 'server'
|
|
@@ -366,6 +371,37 @@ Manager.prototype.loads = async function () {
|
|
|
366
371
|
await Promise.all(promises);
|
|
367
372
|
};
|
|
368
373
|
|
|
374
|
+
/**
|
|
375
|
+
* 获取目录名
|
|
376
|
+
* @returns {string} 目录名
|
|
377
|
+
*/
|
|
378
|
+
Manager.prototype._getDirName = function () {
|
|
379
|
+
// 前缀,为当前类名
|
|
380
|
+
let prefix = this.constructor.name.toLowerCase();
|
|
381
|
+
// 后缀,为配置项名称
|
|
382
|
+
let name = this.config.name.toLowerCase();
|
|
383
|
+
// 目录名,为前缀加下划线加后缀
|
|
384
|
+
return prefix + '_' + name;
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* 获取所有目录下的文件
|
|
389
|
+
* @param {string} dir 目录路径
|
|
390
|
+
* @returns {Array} 文件路径数组
|
|
391
|
+
*/
|
|
392
|
+
Manager.prototype._getAllDirFiles = function (dir) {
|
|
393
|
+
let files = [];
|
|
394
|
+
let dirs = $.dir.getAll(dir, this._getDirName());
|
|
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);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
return files;
|
|
403
|
+
};
|
|
404
|
+
|
|
369
405
|
/**
|
|
370
406
|
* 检索目录下所有文件
|
|
371
407
|
* @private
|
|
@@ -383,6 +419,9 @@ Manager.prototype._findFiles = function (dir) {
|
|
|
383
419
|
this.log('warn', '目录不存在', dir);
|
|
384
420
|
return [];
|
|
385
421
|
}
|
|
422
|
+
if (this.config.search_way === 'dir') {
|
|
423
|
+
return this._getAllDirFiles(dir);
|
|
424
|
+
}
|
|
386
425
|
// 检索目录下所有文件
|
|
387
426
|
return $.file.getAll(dir, this.config.filename);
|
|
388
427
|
};
|
|
@@ -425,7 +464,7 @@ Manager.prototype.update = async function (dir, clear = true) {
|
|
|
425
464
|
}
|
|
426
465
|
|
|
427
466
|
// 查找所有json文件
|
|
428
|
-
let files = this._findFiles(dir);
|
|
467
|
+
let files = this._findFiles(dir || this.config.dir);
|
|
429
468
|
// 批量注册模块
|
|
430
469
|
this.batchRegister(files);
|
|
431
470
|
// 更新配置信息
|
|
@@ -553,7 +592,7 @@ Manager.prototype._runSub = async function (mod, method, ...params) {
|
|
|
553
592
|
|
|
554
593
|
return ret;
|
|
555
594
|
} catch (err) {
|
|
556
|
-
$.log.error(
|
|
595
|
+
$.log.error(`执行模块方法失败: `, err);
|
|
557
596
|
return null;
|
|
558
597
|
}
|
|
559
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
|
-
|
|
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 {
|
|
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
|
|
456
|
+
let ret = await method_func.call(this._mod || this, ...params);
|
|
452
457
|
// 修复:如果主方法返回undefined,则使用前置钩子的结果
|
|
453
|
-
return
|
|
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.
|
|
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"
|