mm_machine 2.1.1 → 2.1.2
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/.prettierrc +8 -0
- package/README.md +583 -576
- package/app/test1/config_demo.json +11 -8
- package/app/test1/demo.json +8 -8
- package/app/test1/index.js +14 -14
- package/app/test2/after.js +6 -6
- package/app/test2/config_demo.json +11 -8
- package/app/test2/demo.json +8 -8
- package/app/test2/index.js +1 -2
- package/app/test2/main.js +8 -8
- package/debug_config.js +37 -0
- package/debug_detailed.js +75 -0
- package/debug_test.js +65 -0
- package/demo/test1/config_demo.json +33 -33
- package/demo/test1/demo.json +33 -33
- package/demo/test1/index.js +19 -16
- package/demo/test2/after.js +9 -9
- package/demo/test2/config_demo.json +70 -68
- package/demo/test2/demo.json +70 -68
- package/demo/test2/index.js +9 -9
- package/demo/test2/main.js +9 -9
- package/demo2/test1/demo.json +33 -33
- package/demo2/test1/index.js +19 -16
- package/demo2/test2/after.js +9 -9
- package/demo2/test2/demo.json +70 -68
- package/demo2/test2/main.js +9 -9
- package/eslint.config.js +209 -0
- package/index.js +625 -571
- package/item.js +672 -589
- package/methods_documentation.md +15 -4
- package/nodemon.json +25 -26
- package/package.json +49 -39
- package/test +3 -0
- package/test.js +124 -107
- package/test.json +9 -0
package/index.js
CHANGED
|
@@ -1,571 +1,625 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @
|
|
3
|
-
* @author <a href="http://qww.elins.cn">邱文武</a>
|
|
4
|
-
* @version 1.6
|
|
5
|
-
*/
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
*
|
|
98
|
-
* @param {
|
|
99
|
-
* @param {
|
|
100
|
-
* @
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
*
|
|
143
|
-
* @
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* 排序
|
|
161
|
-
*/
|
|
162
|
-
Index.prototype.sort = function() {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* 更新前
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
*
|
|
188
|
-
* @
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
*
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
*
|
|
442
|
-
* @
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
};
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @file 机制构建帮助类函数
|
|
3
|
+
* @author <a href="http://qww.elins.cn">邱文武</a>
|
|
4
|
+
* @version 1.6
|
|
5
|
+
*/
|
|
6
|
+
const { Item } = require('./item.js');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @class Index索引类
|
|
10
|
+
*/
|
|
11
|
+
class Index {
|
|
12
|
+
/**
|
|
13
|
+
* 构造函数
|
|
14
|
+
* @param {object} scope 作用域
|
|
15
|
+
* @param {string} dir_base 模块目录
|
|
16
|
+
* @class
|
|
17
|
+
*/
|
|
18
|
+
constructor(scope, dir_base) {
|
|
19
|
+
// 作用域(同时作为检索的后缀名)
|
|
20
|
+
this.scope = scope || ($.val && $.val.scope) ? $.val.scope + '' : '';
|
|
21
|
+
// Index接口列表
|
|
22
|
+
this.list = [];
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* 机制类型
|
|
26
|
+
*/
|
|
27
|
+
this.type = '';
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* 排序项
|
|
31
|
+
*/
|
|
32
|
+
this.sort_key = 'sort';
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* 模块目录
|
|
36
|
+
*/
|
|
37
|
+
this.dir_base = dir_base;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* 模式
|
|
41
|
+
* 1.生产模式,改变文件不会重新加载
|
|
42
|
+
* 2.热更新模式,改变配置文件会重新加载配置,不重新加载脚本
|
|
43
|
+
* 3.热重载模式,改变配置文件都会加载配置和脚本
|
|
44
|
+
* 4.重载模式,执行完后重新加载脚本,避免变量污染
|
|
45
|
+
* 5.热更新+重载模式,改变配置文件重新加载配置和脚本,执行完后重新加载脚本
|
|
46
|
+
*/
|
|
47
|
+
this.mode = 1;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* 私有方法:执行模块方法
|
|
52
|
+
* @param {object} module 模块对象
|
|
53
|
+
* @param {string} method 方法名称
|
|
54
|
+
* @param {Array} params 参数数组
|
|
55
|
+
* @returns {Promise<any>} 执行结果
|
|
56
|
+
* @private
|
|
57
|
+
*/
|
|
58
|
+
async _execute(module, method, params = []) {
|
|
59
|
+
if (!module || !method) return null;
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
// 确保模块已加载
|
|
63
|
+
if (!module.complete) {
|
|
64
|
+
await module.exec('load');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// 执行方法
|
|
68
|
+
const ret = await module.exec(method, ...params);
|
|
69
|
+
|
|
70
|
+
// 根据模式决定是否重载
|
|
71
|
+
if (this.mode >= 4) {
|
|
72
|
+
module.exec('reload');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return ret;
|
|
76
|
+
} catch (err) {
|
|
77
|
+
$.log.error(`[${this.type}] 执行模块方法失败: `, err);
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* 清除接口缓存
|
|
85
|
+
*/
|
|
86
|
+
Index.prototype.clear = function () {
|
|
87
|
+
this.list = [];
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* 默认驱动
|
|
92
|
+
*/
|
|
93
|
+
Index.prototype.Drive = Item;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* 加载项
|
|
97
|
+
* @param {string} dir 文件路径
|
|
98
|
+
* @param {object} cg 配置参数
|
|
99
|
+
* @param {string} file 配置文件
|
|
100
|
+
* @returns {Promise<object | null>} 加载的驱动或配置对象
|
|
101
|
+
*/
|
|
102
|
+
Index.prototype.loadItem = async function (dir, cg, file) {
|
|
103
|
+
if (!dir || !file) {
|
|
104
|
+
$.log.error(`[${this.type}] load: 缺少必要参数`);
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
try {
|
|
109
|
+
if (this.Drive) {
|
|
110
|
+
const drive = new this.Drive(dir, this.dir_base.fullname());
|
|
111
|
+
drive.mode = this.mode;
|
|
112
|
+
if (cg) {
|
|
113
|
+
await drive.exec('loadConfig', file, cg.name);
|
|
114
|
+
await drive.exec('setConfig', cg);
|
|
115
|
+
} else {
|
|
116
|
+
await drive.exec('loadConfig', file);
|
|
117
|
+
}
|
|
118
|
+
this.list.push(drive);
|
|
119
|
+
return drive;
|
|
120
|
+
} else {
|
|
121
|
+
let json = file.loadJson();
|
|
122
|
+
if (!json) {
|
|
123
|
+
const fl = './config.tpl.json'.fullname(this.dir_base);
|
|
124
|
+
if (fl.hasFile()) {
|
|
125
|
+
fl.copyFile(file);
|
|
126
|
+
json = file.loadJson();
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (json) {
|
|
130
|
+
this.list.push(json);
|
|
131
|
+
}
|
|
132
|
+
return json;
|
|
133
|
+
}
|
|
134
|
+
} catch (err) {
|
|
135
|
+
$.log.error(`[${this.type}] 加载项失败: `, err);
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* 加载列表
|
|
142
|
+
* @param {Array} list 文件列表
|
|
143
|
+
* @returns {Promise<void>}
|
|
144
|
+
*/
|
|
145
|
+
Index.prototype.loads = async function (list) {
|
|
146
|
+
// 遍历文件路径
|
|
147
|
+
if (!Array.isArray(list)) {
|
|
148
|
+
$.log.error(`[${this.type}] loads: 列表参数必须是数组`);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// 使用函数式编程,按顺序加载文件
|
|
153
|
+
await list.reduce(async (prev_promise, file_item) => {
|
|
154
|
+
await prev_promise;
|
|
155
|
+
return this.loadFile(file_item, true);
|
|
156
|
+
}, Promise.resolve());
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* 排序
|
|
161
|
+
*/
|
|
162
|
+
Index.prototype.sort = function () {
|
|
163
|
+
this.list.sort((o1, o2) => {
|
|
164
|
+
const p1 = o1.config?.[this.sort_key] || 0;
|
|
165
|
+
const p2 = o2.config?.[this.sort_key] || 0;
|
|
166
|
+
return p2 - p1;
|
|
167
|
+
});
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* 更新前
|
|
172
|
+
* @param {string} dir_path 目录路径
|
|
173
|
+
*/
|
|
174
|
+
Index.prototype.updateBefore = async function (dir_path) {
|
|
175
|
+
// $.log.debug("更新前")
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* 更新后
|
|
180
|
+
* @param {string} dir_path 目录路径
|
|
181
|
+
*/
|
|
182
|
+
Index.prototype.updateAfter = async function (dir_path) {
|
|
183
|
+
// $.log.debug("更新后")
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* 规范化检索路径
|
|
188
|
+
* @param {string} search_path 检索路径
|
|
189
|
+
* @returns {string} 规范化后的路径
|
|
190
|
+
*/
|
|
191
|
+
Index.prototype._normalizeSearchPath = function (search_path) {
|
|
192
|
+
if (!search_path) {
|
|
193
|
+
return './app/';
|
|
194
|
+
}
|
|
195
|
+
// 直接使用传入的路径,不强制添加app/
|
|
196
|
+
return search_path.fullname();
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* 获取目录列表
|
|
201
|
+
* @param {string} norm_path 规范化路径
|
|
202
|
+
* @returns {Array} 目录列表
|
|
203
|
+
*/
|
|
204
|
+
Index.prototype._getDirectoryList = function (norm_path) {
|
|
205
|
+
try {
|
|
206
|
+
// 使用精准模式总是获取所有目录
|
|
207
|
+
// 这样可以确保找到test1和test2目录
|
|
208
|
+
return $.dir.getAll(norm_path);
|
|
209
|
+
} catch (err) {
|
|
210
|
+
$.log.error(`[${this.type}] 检索目录失败!`, err);
|
|
211
|
+
return [];
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* 处理单个目录的配置文件
|
|
217
|
+
* @param {string} dir 目录路径
|
|
218
|
+
* @returns {Promise<void>}
|
|
219
|
+
*/
|
|
220
|
+
Index.prototype._processDirectoryConfig = async function (dir) {
|
|
221
|
+
// 直接检查并加载demo.json文件
|
|
222
|
+
const config_file = `./${this.type}.json`.fullname(dir);
|
|
223
|
+
if (config_file && config_file.hasFile && config_file.hasFile()) {
|
|
224
|
+
await this.loadFile(config_file, true);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// 同时也检查config_demo.json文件
|
|
228
|
+
const config_file2 = `./config_${this.type}.json`.fullname(dir);
|
|
229
|
+
if (config_file2 && config_file2.hasFile && config_file2.hasFile()) {
|
|
230
|
+
await this.loadFile(config_file2, true);
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* 更新所有配置
|
|
236
|
+
* @param {string} search_path 检索路径
|
|
237
|
+
* @param {boolean} accurate 精准路径,默认为false
|
|
238
|
+
* @returns {Promise<void>}
|
|
239
|
+
*/
|
|
240
|
+
Index.prototype.updateConfigAll = async function (search_path, accurate) {
|
|
241
|
+
try {
|
|
242
|
+
// 规范化路径
|
|
243
|
+
const norm_path = this._normalizeSearchPath(search_path);
|
|
244
|
+
|
|
245
|
+
// 获取目录列表
|
|
246
|
+
const list_scope = this._getDirectoryList(norm_path);
|
|
247
|
+
|
|
248
|
+
// 使用函数式编程处理目录
|
|
249
|
+
await list_scope.reduce(async (prev_promise, dir) => {
|
|
250
|
+
await prev_promise;
|
|
251
|
+
return this._processDirectoryConfig(dir);
|
|
252
|
+
}, Promise.resolve());
|
|
253
|
+
} catch (err) {
|
|
254
|
+
$.log.error(`[${this.type}] 更新所有配置失败: `, err);
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* 更新已有配置文件
|
|
260
|
+
* @param {string} dir_path 目录路径
|
|
261
|
+
* @returns {Promise<void>}
|
|
262
|
+
*/
|
|
263
|
+
Index.prototype.updateConfigHave = async function (dir_path) {
|
|
264
|
+
const list = this.list;
|
|
265
|
+
await list.reduce(async (prev_promise, o) => {
|
|
266
|
+
await prev_promise;
|
|
267
|
+
return this._updateSingleConfig(o);
|
|
268
|
+
}, Promise.resolve());
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* 更新单个配置项
|
|
273
|
+
* @param {object} o 配置对象
|
|
274
|
+
*/
|
|
275
|
+
Index.prototype._updateSingleConfig = async function (o) {
|
|
276
|
+
const file = o.filename;
|
|
277
|
+
if (!file) return;
|
|
278
|
+
|
|
279
|
+
try {
|
|
280
|
+
const config = file.loadJson();
|
|
281
|
+
if (!config) return;
|
|
282
|
+
|
|
283
|
+
const target_config = this._findConfig(config, o.config.name);
|
|
284
|
+
if (target_config) {
|
|
285
|
+
await o.exec('setConfig', target_config);
|
|
286
|
+
}
|
|
287
|
+
} catch (err) {
|
|
288
|
+
$.log.error(`[${this.type}] 更新配置失败: `, err);
|
|
289
|
+
}
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* 查找配置项
|
|
294
|
+
* @param {object | Array} config 配置对象
|
|
295
|
+
* @param {string} name 配置名称
|
|
296
|
+
* @returns {object | null} 目标配置
|
|
297
|
+
*/
|
|
298
|
+
Index.prototype._findConfig = function (config, name) {
|
|
299
|
+
if (Array.isArray(config)) {
|
|
300
|
+
return config.find((cg) => cg.name === name) || null;
|
|
301
|
+
}
|
|
302
|
+
return config;
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* 更新配置
|
|
307
|
+
* @param {object} dir - 检索目录
|
|
308
|
+
* @param {boolean} accurate - 精准路径,默认为false
|
|
309
|
+
* @param {boolean} clear - 是否清除现有配置,默认为false
|
|
310
|
+
* @returns {Promise<void>}
|
|
311
|
+
*/
|
|
312
|
+
Index.prototype.updateConfig = async function (dir, accurate = false, clear = false) {
|
|
313
|
+
try {
|
|
314
|
+
if (clear) {
|
|
315
|
+
this.clear();
|
|
316
|
+
await this.updateConfigAll(dir, accurate);
|
|
317
|
+
} else {
|
|
318
|
+
// 如果没有指定目录,则更新已有的配置文件
|
|
319
|
+
await this.updateConfigHave();
|
|
320
|
+
}
|
|
321
|
+
this.sort();
|
|
322
|
+
} catch (err) {
|
|
323
|
+
$.log.error(`[${this.type}] 配置更新失败: `, err);
|
|
324
|
+
}
|
|
325
|
+
};
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* 更新JS
|
|
329
|
+
* @returns {Promise<void>}
|
|
330
|
+
*/
|
|
331
|
+
Index.prototype.updateScript = async function () {
|
|
332
|
+
const list = this.list;
|
|
333
|
+
await list.reduce(async (prev_promise, o) => {
|
|
334
|
+
await prev_promise;
|
|
335
|
+
if (o.config?.state === 1) {
|
|
336
|
+
return o.exec('loadScript');
|
|
337
|
+
}
|
|
338
|
+
}, Promise.resolve());
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* 更新
|
|
343
|
+
* @param {string} dir 检索的路径
|
|
344
|
+
* @param {boolean} accurate 是否精准路径,默认为false
|
|
345
|
+
* @param {boolean} loadJS 是否加载JS,默认为true
|
|
346
|
+
* @param {boolean} clear 是否清除现有配置,默认为true
|
|
347
|
+
* @returns {Promise<void>}
|
|
348
|
+
*/
|
|
349
|
+
Index.prototype.updateMain = async function (dir, accurate = false, loadJS = true, clear = true) {
|
|
350
|
+
await this.updateConfig(dir, accurate, clear);
|
|
351
|
+
if (loadJS) {
|
|
352
|
+
await this.updateScript();
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* 更新配置
|
|
358
|
+
* @param {string} dir 检索的路径
|
|
359
|
+
* @param {boolean} accurate 精准路径
|
|
360
|
+
* @param {boolean} loadJS 是否加载JS
|
|
361
|
+
* @param {boolean} clear 是否清除缓存
|
|
362
|
+
*/
|
|
363
|
+
Index.prototype.update = async function (dir, accurate = false, loadJS = true, clear = true) {
|
|
364
|
+
await this.updateBefore(dir);
|
|
365
|
+
await this.updateMain(dir, accurate, loadJS, clear);
|
|
366
|
+
await this.updateAfter(dir);
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* 查询配置项
|
|
371
|
+
* @param {string} name 名称
|
|
372
|
+
* @returns {object | null} 返回单项配置
|
|
373
|
+
*/
|
|
374
|
+
Index.prototype.get = function (name) {
|
|
375
|
+
if (!name) return null;
|
|
376
|
+
return this.list.find((item) => item.config?.name === name) || null;
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* 设置配置项
|
|
381
|
+
* @param {string} name 配置项名称
|
|
382
|
+
* @param {object} cg 配置对象
|
|
383
|
+
* @returns {boolean} 是否设置成功
|
|
384
|
+
*/
|
|
385
|
+
Index.prototype.set = function (name, cg) {
|
|
386
|
+
if (!name || !cg) return false;
|
|
387
|
+
|
|
388
|
+
const item = this.get(name);
|
|
389
|
+
if (item) {
|
|
390
|
+
// 使用Object.assign合并属性
|
|
391
|
+
Object.assign(item.config, cg);
|
|
392
|
+
return true;
|
|
393
|
+
}
|
|
394
|
+
return false;
|
|
395
|
+
};
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* 保存
|
|
399
|
+
* @returns {boolean} 是否保存成功
|
|
400
|
+
*/
|
|
401
|
+
Index.prototype.save = async function () {
|
|
402
|
+
const list = this.list;
|
|
403
|
+
await list.reduce(async (prev_promise, o) => {
|
|
404
|
+
await prev_promise;
|
|
405
|
+
if (o.config?.state === 1) {
|
|
406
|
+
return o.exec('save');
|
|
407
|
+
}
|
|
408
|
+
}, Promise.resolve());
|
|
409
|
+
};
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* 添加插件
|
|
413
|
+
* @param {object} config 配置对象
|
|
414
|
+
* @returns {Promise<object | null>} 新添加的插件对象
|
|
415
|
+
*/
|
|
416
|
+
Index.prototype.add = async function (config) {
|
|
417
|
+
if (!config || !config.name) {
|
|
418
|
+
$.log.error(`[${this.type}] 添加插件失败: 缺少必要的配置信息`);
|
|
419
|
+
return null;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
try {
|
|
423
|
+
// 检查是否已存在
|
|
424
|
+
const existing = this.get(config.name);
|
|
425
|
+
if (existing) {
|
|
426
|
+
$.log.warn(`插件 ${config.name} 已存在`);
|
|
427
|
+
return existing;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
const item = new Item(this, config);
|
|
431
|
+
this.list.push(item);
|
|
432
|
+
this.sort();
|
|
433
|
+
return item;
|
|
434
|
+
} catch (err) {
|
|
435
|
+
$.log.error(`[${this.type}] 添加插件失败: `, err);
|
|
436
|
+
return null;
|
|
437
|
+
}
|
|
438
|
+
};
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* 删除插件
|
|
442
|
+
* @param {string} name 插件名称
|
|
443
|
+
* @returns {Promise<boolean>} 是否删除成功
|
|
444
|
+
*/
|
|
445
|
+
Index.prototype.del = async function (name) {
|
|
446
|
+
if (!name) return false;
|
|
447
|
+
|
|
448
|
+
const index = this.list.findIndex((item) => item.config?.name === name);
|
|
449
|
+
if (index === -1) return false;
|
|
450
|
+
|
|
451
|
+
try {
|
|
452
|
+
const item = this.list[index];
|
|
453
|
+
await item.exec('unload');
|
|
454
|
+
this.list.splice(index, 1);
|
|
455
|
+
return true;
|
|
456
|
+
} catch (err) {
|
|
457
|
+
$.log.error(`[${this.type}] 删除插件失败: `, err);
|
|
458
|
+
return false;
|
|
459
|
+
}
|
|
460
|
+
};
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* 加载插件
|
|
464
|
+
* @param {string} name 插件名称
|
|
465
|
+
* @returns {Promise<object | null>} 加载的插件对象
|
|
466
|
+
*/
|
|
467
|
+
Index.prototype.load = async function (name) {
|
|
468
|
+
if (!name) return null;
|
|
469
|
+
|
|
470
|
+
const item = this.get(name);
|
|
471
|
+
if (!item) return null;
|
|
472
|
+
|
|
473
|
+
try {
|
|
474
|
+
if (item.config?.state === 1) {
|
|
475
|
+
await item.exec('load');
|
|
476
|
+
}
|
|
477
|
+
return item;
|
|
478
|
+
} catch (err) {
|
|
479
|
+
$.log.error(`[${this.type}] 加载插件 ${name} 失败: `, err);
|
|
480
|
+
return null;
|
|
481
|
+
}
|
|
482
|
+
};
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* 卸载插件
|
|
486
|
+
* @param {string} name 插件名称
|
|
487
|
+
* @returns {Promise<boolean>} 是否卸载成功
|
|
488
|
+
*/
|
|
489
|
+
Index.prototype.unload = async function (name) {
|
|
490
|
+
if (!name) return false;
|
|
491
|
+
|
|
492
|
+
const item = this.get(name);
|
|
493
|
+
if (!item) return false;
|
|
494
|
+
|
|
495
|
+
try {
|
|
496
|
+
await item.exec('unload');
|
|
497
|
+
return true;
|
|
498
|
+
} catch (err) {
|
|
499
|
+
$.log.error(`[${this.type}] 卸载插件 ${name} 失败: `, err);
|
|
500
|
+
return false;
|
|
501
|
+
}
|
|
502
|
+
};
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* 重新加载插件
|
|
506
|
+
* @param {string} name 插件名称
|
|
507
|
+
* @returns {Promise<object | null>} 重新加载的插件对象
|
|
508
|
+
*/
|
|
509
|
+
Index.prototype.reload = async function (name) {
|
|
510
|
+
if (!name) return null;
|
|
511
|
+
|
|
512
|
+
const item = this.get(name);
|
|
513
|
+
if (!item) return null;
|
|
514
|
+
|
|
515
|
+
try {
|
|
516
|
+
await item.exec('reload');
|
|
517
|
+
return item;
|
|
518
|
+
} catch (err) {
|
|
519
|
+
$.log.error(`[${this.type}] 重新加载插件 ${name} 失败: `, err);
|
|
520
|
+
return null;
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* 通过文件加载配置
|
|
526
|
+
* @param {string} file 文件名
|
|
527
|
+
* @param {boolean} create 不存在则进行创建
|
|
528
|
+
* @returns {Promise<object | null | string>} 加载的驱动对象、null或错误信息
|
|
529
|
+
*/
|
|
530
|
+
Index.prototype.loadFile = async function (file, create = false) {
|
|
531
|
+
try {
|
|
532
|
+
const dir = file.dirname();
|
|
533
|
+
// 载入文件
|
|
534
|
+
const obj = file.loadJson();
|
|
535
|
+
if (obj) {
|
|
536
|
+
if (Array.isArray(obj)) {
|
|
537
|
+
// 使用函数式编程处理数组
|
|
538
|
+
await obj.reduce(async (prev_promise, o) => {
|
|
539
|
+
await prev_promise;
|
|
540
|
+
// 实例化一个驱动
|
|
541
|
+
return this.loadItem(dir, o, file);
|
|
542
|
+
}, Promise.resolve());
|
|
543
|
+
} else {
|
|
544
|
+
return await this.loadItem(dir, null, file);
|
|
545
|
+
}
|
|
546
|
+
} else if (create) {
|
|
547
|
+
return await this.loadItem(dir, null, file);
|
|
548
|
+
} else {
|
|
549
|
+
return `${file}文件不存在`;
|
|
550
|
+
}
|
|
551
|
+
return null;
|
|
552
|
+
} catch (err) {
|
|
553
|
+
$.log.error(`[${this.type}] 加载文件失败: `, err);
|
|
554
|
+
return `加载文件失败: ${err.message}`;
|
|
555
|
+
}
|
|
556
|
+
};
|
|
557
|
+
|
|
558
|
+
/**
|
|
559
|
+
* 调用函数
|
|
560
|
+
* @param {string} name 模块名
|
|
561
|
+
* @param {string} method 函数名
|
|
562
|
+
* @param {object} params 参数集合
|
|
563
|
+
* @returns {Promise<any>} 执行结果
|
|
564
|
+
*/
|
|
565
|
+
Index.prototype.run = async function (name, method, ...params) {
|
|
566
|
+
if (name) {
|
|
567
|
+
const module = await this.get(name);
|
|
568
|
+
if (module && module.config?.state === 1) {
|
|
569
|
+
return await this._execute(module, method, params);
|
|
570
|
+
}
|
|
571
|
+
return null;
|
|
572
|
+
} else if (name === null) {
|
|
573
|
+
let result = null;
|
|
574
|
+
// 使用函数式编程处理列表,使用some模拟break逻辑
|
|
575
|
+
await this.list.some(async (module) => {
|
|
576
|
+
if (module.config?.state === 1) {
|
|
577
|
+
result = await this._execute(module, method, params);
|
|
578
|
+
// 如果结果不为空且有结束标志,则停止迭代
|
|
579
|
+
return result && module.config?.end;
|
|
580
|
+
}
|
|
581
|
+
return false;
|
|
582
|
+
});
|
|
583
|
+
return result;
|
|
584
|
+
}
|
|
585
|
+
return null;
|
|
586
|
+
};
|
|
587
|
+
|
|
588
|
+
/**
|
|
589
|
+
* 执行方法
|
|
590
|
+
* @param {string} name 插件名称
|
|
591
|
+
* @param {string} method 方法名称
|
|
592
|
+
* @param {...any} params 方法参数
|
|
593
|
+
* @returns {Promise<any>} 执行结果
|
|
594
|
+
*/
|
|
595
|
+
Index.prototype.exec = async function (name, method, ...params) {
|
|
596
|
+
if (name) {
|
|
597
|
+
const module = await this.get(name);
|
|
598
|
+
if (module) {
|
|
599
|
+
return await this._execute(module, method, params);
|
|
600
|
+
}
|
|
601
|
+
return null;
|
|
602
|
+
} else if (name === null) {
|
|
603
|
+
let result = null;
|
|
604
|
+
// 使用函数式编程处理列表,使用reduce模拟break逻辑
|
|
605
|
+
await this.list.reduce(async (prev_promise, module) => {
|
|
606
|
+
await prev_promise;
|
|
607
|
+
// 如果已经得到结果且有结束标志,则跳过后续处理
|
|
608
|
+
if (result && module.config?.end) {
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
611
|
+
const current_result = await this._execute(module, method, params);
|
|
612
|
+
if (current_result) {
|
|
613
|
+
result = current_result;
|
|
614
|
+
}
|
|
615
|
+
}, Promise.resolve());
|
|
616
|
+
return result;
|
|
617
|
+
}
|
|
618
|
+
return null;
|
|
619
|
+
};
|
|
620
|
+
|
|
621
|
+
/**
|
|
622
|
+
* @module 导出Index类
|
|
623
|
+
*/
|
|
624
|
+
exports.Index = Index;
|
|
625
|
+
exports.Item = Item;
|