mm_os 5.0.0 → 5.0.1

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
@@ -7,7 +7,8 @@
7
7
  - `OS` 类:初始化日志、管理、适配器、存储与应用加载器
8
8
  - 输入适配器:web / mqtt / socket / websocket
9
9
  - 输出适配器:redis / mongodb / mysql / sqlite / jsondb / file
10
- - 工具与管理:lang / tpl / ret / service / handle / event / api / param / sql / templete / pendant / timer / statics
10
+ - 工具:lang / tpl / ret
11
+ - 管理:service / handle / event / api / param / dao / templete / pendant / timer / statics
11
12
  - `Loader` 类:扫描应用目录,加载应用与插件的配置、生命周期和资源清单
12
13
  - `osAdmin(scope, config)` 按作用域缓存系统实例,相同 `scope` 返回同一实例
13
14
 
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  const OS = require('./lib/os');
2
- const Loader = require('./lib/loader');
2
+ const { Loader } = require('mm_loader');
3
3
  const Admin = require('mm_corejs').Admin;
4
4
 
5
5
  let admin = new Admin();
package/lib/os.js CHANGED
@@ -1,6 +1,10 @@
1
- const { Mod, Store } = require('mm_corejs');
1
+ const path = require('path');
2
+ const { Mod } = require('mm_mod');
3
+ const { containerAdmin } = require('mm_container');
2
4
  const { getLogger } = require('mm_logger');
3
- const Loader = require('./loader');
5
+ const { Loader } = require('mm_loader');
6
+ const { appAdmin } = require('mm_apps');
7
+ const { eventAdmin } = require('mm_event');
4
8
 
5
9
  /**
6
10
  * OS类
@@ -8,18 +12,85 @@ const Loader = require('./loader');
8
12
  class OS extends Mod {
9
13
  static config = {
10
14
  name: 'os',
11
- in_adapters: ['web', 'mqtt', 'socket', 'websocket'],
12
- out_adapters: ['redis', 'mongodb', 'mysql', 'sqlite', 'jsondb', 'file'],
13
- tools: ['lang', 'tpl', 'ret'],
14
- admins: ['handle', 'event', 'api', 'param', 'service', 'template', 'pendant', 'timer', 'statics'],
15
+ in_adapters: [{
16
+ name: 'web',
17
+ module: 'mm_web_server'
18
+ }, {
19
+ name: 'mqtt',
20
+ module: 'mm_mqtt_server'
21
+ }, {
22
+ name: 'socket',
23
+ module: 'mm_socket_server'
24
+ }, {
25
+ name: 'websocket',
26
+ module: 'mm_websocket_server'
27
+ }],
28
+ // 输出适配器
29
+ out_adapters: [{
30
+ name: 'redis',
31
+ module: 'mm_redis'
32
+ }, {
33
+ name: 'mongodb',
34
+ module: 'mm_mongodb'
35
+ }, {
36
+ name: 'mysql',
37
+ module: 'mm_mysql'
38
+ }, {
39
+ name: 'sqlite',
40
+ module: 'mm_sqlite'
41
+ }, {
42
+ name: 'jsondb',
43
+ module: 'mm_jsondb'
44
+ }, {
45
+ name: 'file',
46
+ module: 'mm_files'
47
+ }],
48
+ tools: [{
49
+ name: 'lang',
50
+ module: 'mm_lang'
51
+ }, {
52
+ name: 'tpl',
53
+ module: 'mm_tpl'
54
+ }, {
55
+ name: 'ret',
56
+ module: 'mm_ret'
57
+ }],
58
+ admins: [{
59
+ name: 'event',
60
+ module: 'mm_event'
61
+ }, {
62
+ name: 'api',
63
+ module: 'mm_api'
64
+ }, {
65
+ name: 'param',
66
+ module: 'mm_param'
67
+ }, {
68
+ name: 'dao',
69
+ module: 'mm_dao'
70
+ }, {
71
+ name: 'service',
72
+ module: 'mm_service'
73
+ }, {
74
+ name: 'template',
75
+ module: 'mm_template'
76
+ }, {
77
+ name: 'pendant',
78
+ module: 'mm_pendant'
79
+ }, {
80
+ name: 'timer',
81
+ module: 'mm_timer'
82
+ }, {
83
+ name: 'static',
84
+ module: 'mm_statics'
85
+ }],
15
86
  cache: {
16
87
  type: 'redis'
17
88
  },
18
- db: {
89
+ sql: {
19
90
  type: 'mysql'
20
91
  },
21
92
  web: {
22
- port: 8080
93
+ port: 8000
23
94
  },
24
95
  mqtt: {
25
96
  port: 1883
@@ -68,6 +139,9 @@ class OS extends Mod {
68
139
  tpl: {
69
140
  dir: './static/template',
70
141
  ext: '.html'
142
+ },
143
+ loader: {
144
+ dir: ''
71
145
  }
72
146
  }
73
147
 
@@ -78,20 +152,11 @@ class OS extends Mod {
78
152
  constructor(config) {
79
153
  super(config);
80
154
  /**
81
- * 管理列表
82
- * @type {Store}
83
- */
84
- this.admins = new Store();
85
- /**
86
- * 输入适配器列表
87
- * @type {Store}
88
- */
89
- this.in_adapters = new Store();
90
- /**
91
- * 输出适配器列表
92
- * @type {Store}
155
+ * 实例容器(按作用域共享)
156
+ * @type {object}
93
157
  */
94
- this.out_adapters = new Store();
158
+ this.container = containerAdmin('os', { name: 'os' });
159
+ this.container.server = this;
95
160
  }
96
161
 
97
162
  /**
@@ -99,21 +164,49 @@ class OS extends Mod {
99
164
  * @returns {void} 无返回值
100
165
  */
101
166
  async onInit() {
167
+ this.initConfig();
102
168
  this.initLogger();
103
169
  // 初始化事件总线
104
170
  this.initEventBus();
171
+ // 存储需先于管理器初始化:mm_dao 等管理器会通过 mm_sql 的 getSql() 复用同名 SQL 实例,
172
+ // 若管理器先创建,则会以默认(空库名)配置占用实例,导致后续 SQL 报 No database selected
173
+ await this.initpStorage();
105
174
  await this.initAdmins();
106
175
  await this.initAdapter();
107
- await this.initpStorage();
108
176
  await this.initLoader();
109
177
  }
110
178
  }
111
179
 
180
+ /**
181
+ * 初始化配置管理器
182
+ */
183
+ OS.prototype.initConfig = function () {
184
+ const { admin } = require('mm_config');
185
+ admin.setServer(this);
186
+ admin.get('os', this.config);
187
+ admin.get('cache', { ...this.config.cache, redis: this.config.redis, mongodb: this.config.mongodb });
188
+ admin.get('sql', { ...this.config.sql, mysql: this.config.mysql, sqlite: this.config.sqlite, jsondb: this.config.jsondb });
189
+ admin.get('web', this.config.web);
190
+ admin.get('mqtt', this.config.mqtt);
191
+ admin.get('socket', this.config.socket);
192
+ admin.get('websocket', this.config.websocket);
193
+ admin.get('jsondb', this.config.jsondb);
194
+ admin.get('redis', this.config.redis);
195
+ admin.get('mongodb', this.config.mongodb);
196
+ admin.get('sqlite', this.config.sqlite);
197
+ admin.get('mysql', this.config.mysql);
198
+ admin.get('ret', this.config.ret);
199
+ admin.get('lang', this.config.lang);
200
+ admin.get('tpl', this.config.tpl);
201
+ admin.get('loader', this.config.loader);
202
+ this.reg('config', admin);
203
+ };
204
+
112
205
  /**
113
206
  * 初始化日志记录器
114
207
  */
115
208
  OS.prototype.initLogger = function () {
116
- this.logger = getLogger(this.config.log || { level: 'info' });
209
+ this.reg('logger', getLogger(this.config.log || { level: 'info' }));
117
210
  };
118
211
 
119
212
  /**
@@ -123,7 +216,7 @@ OS.prototype.initLogger = function () {
123
216
  * @param {...*} args 日志参数
124
217
  */
125
218
  OS.prototype.log = function (type, msg, ...args) {
126
- this.logger[type](msg, ...args);
219
+ this.container.get('logger')[type](msg, ...args);
127
220
  };
128
221
 
129
222
  /**
@@ -132,7 +225,7 @@ OS.prototype.log = function (type, msg, ...args) {
132
225
  * @param {object} admin 管理对象
133
226
  */
134
227
  OS.prototype.reg = function (name, admin) {
135
- this.admins.add({ id: name, name: name, admin });
228
+ this.container.set(name, admin);
136
229
  };
137
230
 
138
231
  /**
@@ -151,75 +244,54 @@ OS.prototype.require = function (mod_name) {
151
244
  OS.prototype.initAdapter = async function () {
152
245
  // 入站适配器
153
246
  let adapters = this.config.in_adapters || [];
154
- for (let name of adapters) {
247
+ for (let mod of adapters) {
155
248
  try {
156
- let admin = this.require(`mm_${name}_server`).admin;
249
+ let admin = this.require(mod.module).admin;
157
250
  admin.setServer(this);
158
- let manager = admin.get('os', this.config[name]);
159
- this._useMiddleware(name, manager);
251
+ let manager = admin.get('os', this.config[mod.name]);
160
252
  if (typeof manager.init === 'function') {
161
253
  await manager.init();
162
254
  }
163
- this.in_adapters.add({ id: name, name: name, admin: manager });
255
+ this.reg(mod.name, manager);
164
256
  } catch (error) {
165
- this.log('error', `初始化适配器 ${name} 失败: ${error}`);
257
+ this.log('error', `初始化适配器 ${mod.name} 失败: ${error}`);
166
258
  }
167
259
  }
168
260
 
169
261
  // 出站适配器
170
262
  let out_adapters = this.config.out_adapters || [];
171
- for (let name of out_adapters) {
263
+ for (let mod of out_adapters) {
172
264
  try {
173
- let admin = this.require(`mm_${name}`).admin;
265
+ let admin = this.require(mod.module).admin;
174
266
  admin.setServer(this);
175
- let manager = admin.get('os', this.config[name]);
267
+ let manager = admin.get('os', this.config[mod.name]);
176
268
  if (typeof manager.init === 'function') {
177
269
  await manager.init();
178
270
  }
179
- this.out_adapters.add({ id: name, name: name, admin: manager });
271
+ this.reg(mod.name, manager);
180
272
  } catch (error) {
181
- this.log('error', `初始化适配器 ${name} 失败: ${error}`);
273
+ this.log('error', `初始化适配器 ${mod.name} 失败: ${error}`);
182
274
  }
183
275
  }
184
276
  };
185
277
 
186
- /**
187
- * 装配中间件:web 适配器挂载页面渲染中间件与静态资源插件,
188
- * 使 HTML 页面以正确内容类型输出,并让注册到 mm_statics 的静态文件可被直接访问
189
- * @param {string} name 适配器名称(web / socket / mqtt / websocket)
190
- * @param {object} manager 适配器管理器实例
191
- * @returns {void} 无返回值
192
- * @private
193
- */
194
- OS.prototype._useMiddleware = function (name, manager) {
195
- if (name !== 'web' || !manager || typeof manager.use !== 'function') return;
196
- try {
197
- const { Render } = this.require('mm_render');
198
- manager.use(new Render());
199
- const statics_mod = this.require('mm_statics');
200
- manager.use(new statics_mod.StaticsPlugin({ admin: statics_mod.admin }));
201
- } catch (error) {
202
- this.log('error', `装配渲染中间件失败: ${error.message}`);
203
- }
204
- };
205
-
206
278
  /**
207
279
  * 初始化工具
208
280
  * @returns {void} 无返回值
209
281
  */
210
282
  OS.prototype.initTools = async function () {
211
283
  let tools = this.config.tools || [];
212
- for (let name of tools) {
284
+ for (let mod of tools) {
213
285
  try {
214
- let admin = this.require(`mm_${name}`).admin;
286
+ let admin = this.require(mod.module).admin;
215
287
  admin.setServer(this);
216
- let manager = admin.get('os', this.config[name]);
288
+ let manager = admin.get('os', this.config[mod.name]);
217
289
  if (typeof manager.init === 'function') {
218
290
  await manager.init();
219
291
  }
220
- this.reg(name, manager);
292
+ this.reg(mod.name, manager);
221
293
  } catch (error) {
222
- this.log('error', `初始化工具 ${name} 失败: ${error}`);
294
+ this.log('error', `初始化工具 ${mod.name} 失败: ${error}`);
223
295
  }
224
296
  }
225
297
  };
@@ -230,17 +302,17 @@ OS.prototype.initTools = async function () {
230
302
  */
231
303
  OS.prototype.initAdmins = async function () {
232
304
  let admins = this.config.admins || [];
233
- for (let name of admins) {
305
+ for (let mod of admins) {
234
306
  try {
235
- let admin = this.require(`mm_${name}`).admin;
307
+ let admin = this.require(mod.module).admin;
236
308
  admin.setServer(this);
237
- let manager = admin.get('os', this.config[name]);
309
+ let manager = admin.get('os', this.config[mod.name]);
238
310
  if (typeof manager.init === 'function') {
239
311
  await manager.init();
240
312
  }
241
- this.reg(name, manager);
313
+ this.reg(mod.name, manager);
242
314
  } catch (error) {
243
- this.log('error', `初始化管理 ${name} 失败: ${error}`);
315
+ this.log('error', `初始化管理 ${mod.name} 失败: ${error}`);
244
316
  }
245
317
  }
246
318
  };
@@ -257,7 +329,7 @@ OS.prototype.initpStorage = async function () {
257
329
  if (typeof cache.init === 'function') {
258
330
  await cache.init();
259
331
  }
260
- this.cache = cache;
332
+ this.reg('cache', cache);
261
333
 
262
334
  // 初始化数据库
263
335
  let sqlAdmin = this.require('mm_sql').admin;
@@ -266,7 +338,7 @@ OS.prototype.initpStorage = async function () {
266
338
  if (typeof sql.init === 'function') {
267
339
  await sql.init();
268
340
  }
269
- this.sql = sql;
341
+ this.reg('sql', sql);
270
342
  };
271
343
 
272
344
  /**
@@ -280,90 +352,185 @@ OS.prototype._setAdminServer = function (admin) {
280
352
  };
281
353
 
282
354
  /**
283
- * 初始化应用加载器
355
+ * 初始化应用加载器(协调层:只创建加载器与应用管理器,装配逻辑在 mm_apps/mm_plugins)
284
356
  * @returns {void} 无返回值
285
357
  */
286
358
  OS.prototype.initLoader = async function () {
287
- let loader = new Loader(this.config.loader || {}, this);
288
- loader.setLogger(this.logger);
289
- await loader.init();
290
- this.loader = loader;
359
+ // 配置加载器:注入 socket/mqtt 类型,其余类型由 mm_loader 默认提供
360
+ const loader = new Loader(this.config.loader || {});
361
+ loader.addType('socket', 'socket.json');
362
+ loader.addType('mqtt', 'mqtt.json');
363
+ this.reg('loader', loader);
364
+
365
+ // 应用管理器:装配应用由 AppManager.load 负责,插件随 App.onInit 引入
366
+ const app = appAdmin('os');
367
+ app.setServer(this);
368
+ app.setLogger(this.container.get('logger'));
369
+ this.reg('app', app);
370
+
371
+ const dir = this.config.loader.dir || path.join(__dirname, '..', 'example', 'app');
372
+ await app.load(dir, loader);
373
+ await app.init();
374
+
375
+ // 注入 Web 请求路由
376
+ this._initWeb();
291
377
  };
292
378
 
293
379
  /**
294
- * 初始化事件总线
380
+ * 初始化 Web 适配器:注入跨作用域事件路由
295
381
  * @returns {void} 无返回值
296
382
  */
297
- OS.prototype.initEventBus = function () {
298
- let admin = this.require('mm_eventer').admin;
299
- admin.setServer(this);
300
- this.eventer = admin.get('os');
383
+ OS.prototype._initWeb = function () {
384
+ const web = this.container.get('web');
385
+ if (!web) return;
386
+ web.setEventManager(this._createEventRouter());
301
387
  };
302
388
 
303
389
  /**
304
- * 启动入站适配器
305
- * @returns {void} 无返回值
390
+ * 创建跨作用域事件路由:Web 适配器只持有 web 作用域,需转发到各应用作用域
391
+ * @returns {object} 含 run 方法的事件管理器
306
392
  */
307
- OS.prototype._startInAdapters = async function () {
308
- let in_adapters = this.in_adapters.list();
309
- for (let item of in_adapters) {
310
- try {
311
- await item.admin.start();
312
- this._printAddress(item);
313
- } catch (error) {
314
- this.log('error', `启动适配器 ${item.name} 失败: ${error}`);
393
+ OS.prototype._createEventRouter = function () {
394
+ return {
395
+ run: (target, params, ctx, options) => this._routeRequest(target, params, ctx, options)
396
+ };
397
+ };
398
+
399
+ /**
400
+ * 路由请求:先尝试静态资源,未命中再按应用顺序执行事件
401
+ * @param {string} target 请求路径
402
+ * @param {object} params 请求参数
403
+ * @param {object} ctx 请求上下文
404
+ * @param {object} options 事件运行选项
405
+ * @returns {Promise<*>} 事件执行结果
406
+ */
407
+ OS.prototype._routeRequest = async function (target, params, ctx, options = {}) {
408
+ const statics = this.container.get('static');
409
+ if (!statics || typeof statics.run !== 'function') {
410
+ return await this._runAppEvents(target, params, ctx, options);
411
+ }
412
+ let result;
413
+ await statics.run(ctx, async () => {
414
+ result = await this._runAppEvents(target, params, ctx, options);
415
+ });
416
+ return result;
417
+ };
418
+
419
+ /**
420
+ * 按应用排序依次执行事件:命中结果、响应已写出或发生错误时中止
421
+ * @param {string} target 请求路径
422
+ * @param {object} params 请求参数
423
+ * @param {object} ctx 请求上下文
424
+ * @param {object} options 事件运行选项
425
+ * @returns {Promise<*>} 事件执行结果
426
+ */
427
+ OS.prototype._runAppEvents = async function (target, params, ctx, options = {}) {
428
+ const app = this.container.get('app');
429
+ if (!app || typeof app.list !== 'function') return undefined;
430
+
431
+ const apps = app.list().slice().sort((a, b) => this._getSort(a) - this._getSort(b));
432
+ for (const item of apps) {
433
+ if (this._isRequestHandled(ctx) || ctx.error) return undefined;
434
+ const name = item.config && item.config.name;
435
+ if (!name) continue;
436
+ const app_options = {};
437
+ const result = await eventAdmin(name).run(target, params, ctx, app_options);
438
+ if (app_options.error) {
439
+ ctx.error = ctx.error || app_options.error;
440
+ options.error = options.error || app_options.error;
441
+ return undefined;
315
442
  }
443
+ if (result !== undefined && result !== null) return result;
316
444
  }
445
+ return undefined;
317
446
  };
318
447
 
319
448
  /**
320
- * 启动出站适配器
449
+ * 判断请求是否已处理完毕:事件或中间件已写出响应
450
+ * @param {object} ctx 请求上下文
451
+ * @returns {boolean} 响应是否已写出
452
+ */
453
+ OS.prototype._isRequestHandled = function (ctx) {
454
+ if (!ctx) return false;
455
+ if (ctx.handled === true) return true;
456
+ const res = ctx.res;
457
+ return !!(res && (res.writableEnded || res.headersSent));
458
+ };
459
+
460
+ /**
461
+ * 获取应用执行顺序
462
+ * @param {object} app 应用驱动实例
463
+ * @returns {number} 排序值,缺省 100
464
+ */
465
+ OS.prototype._getSort = function (app) {
466
+ const sort = app && app.config ? app.config.sort : undefined;
467
+ return typeof sort === 'number' ? sort : 100;
468
+ };
469
+
470
+ /**
471
+ * 初始化事件总线
472
+ * @returns {void} 无返回值
473
+ */
474
+ OS.prototype.initEventBus = function () {
475
+ let admin = this.require('mm_eventer').admin;
476
+ admin.setServer(this);
477
+ this.reg('eventer', admin.get('os'));
478
+ };
479
+
480
+ /**
481
+ * 启动适配器:按配置中的入站、出站适配器名称从容器取出管理器并启动
321
482
  * @returns {void} 无返回值
322
483
  */
323
- OS.prototype._startOutAdapters = async function () {
324
- let out_adapters = this.out_adapters.list();
325
- for (let item of out_adapters) {
484
+ OS.prototype._startAdapters = async function () {
485
+ let mods = this.config.in_adapters;
486
+ for (let mod of mods) {
487
+ let manager = this.container.get(mod.name);
488
+ if (!manager || typeof manager.start !== 'function') continue;
326
489
  try {
327
- await item.admin.start();
328
- this._printAddress(item);
490
+ await manager.start();
491
+ this._printAddress(mod.name, manager);
329
492
  } catch (error) {
330
- this.log('error', `启动适配器 ${item.name} 失败: ${error}`);
493
+ this.log('error', `启动适配器 ${mod.name} 失败: ${error}`);
331
494
  }
332
495
  }
333
496
  };
334
497
 
335
498
  /**
336
- * 启动适配器
499
+ * 启动
337
500
  * @returns {void} 无返回值
338
501
  */
339
502
  OS.prototype.start = async function () {
340
- // 启动入站适配器
341
- await this._startInAdapters();
342
- // 启动出站适配器
343
- await this._startOutAdapters();
503
+ // 启动适配器
504
+ await this._startAdapters();
344
505
 
345
506
  // 启动缓存存储
346
- await this.cache.start();
507
+ await this.container.get('cache').start();
347
508
  // 启动数据库
348
- await this.sql.start();
509
+ await this.container.get('sql').start();
349
510
 
350
511
  // 启动应用
351
- if (this.loader) {
352
- await this.loader.start();
512
+ const app = this.container.get('app');
513
+ if (app) {
514
+ await app.start();
353
515
  }
354
516
  };
355
517
 
356
518
  /**
357
519
  * 打印适配器监听地址
358
- * @param {object} item 适配器存储项,含 name 与 admin
520
+ * @param {string} name 适配器名称
521
+ * @param {object} manager 适配器管理器实例
359
522
  */
360
- OS.prototype._printAddress = function (item) {
361
- let { host, port } = item.admin.config || {};
523
+ OS.prototype._printAddress = function (name, manager) {
524
+ let { host, port } = manager.config || {};
362
525
  if (!host || host === '0.0.0.0' || host === '::') {
363
526
  host = 'localhost';
364
527
  }
365
- let protocol = { web: 'http', websocket: 'ws', socket: 'tcp', mqtt: 'mqtt' }[item.name] || item.name;
366
- this.log('info', `适配器 ${item.name} 已启动: ${protocol}://${host}:${port}`);
528
+ let protocol = { web: 'http', websocket: 'ws', socket: 'tcp', mqtt: 'mqtt' }[name] || name;
529
+ let address = `${protocol}://${host}`;
530
+ if (port) {
531
+ address += `:${port}`;
532
+ }
533
+ this.log('info', `适配器 ${name} 已启动: ${address}`);
367
534
  };
368
535
 
369
536
  module.exports = OS;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mm_os",
3
- "version": "5.0.0",
3
+ "version": "5.0.1",
4
4
  "description": "这是OS系统",
5
5
  "repository": {
6
6
  "type": "git",
@@ -26,30 +26,35 @@
26
26
  },
27
27
  "dependencies": {
28
28
  "markdown": "^0.5.0",
29
- "mm_app": "^1.0.0",
30
- "mm_cache": "^1.5.4",
31
- "mm_corejs": "^1.1.4",
29
+ "mm_apps": "^1.0.2",
30
+ "mm_cache": "^1.5.5",
31
+ "mm_container": "^1.0.1",
32
+ "mm_corejs": "^1.1.5",
33
+ "mm_dao": "^1.8.0",
32
34
  "mm_es6_to_amd": "^1.5.9",
33
- "mm_event": "^2.2.0",
34
- "mm_file": "^1.0.0",
35
+ "mm_event": "^2.2.4",
36
+ "mm_files": "^1.0.0",
35
37
  "mm_handle": "^1.0.0",
36
38
  "mm_jsondb": "^1.0.0",
39
+ "mm_loader": "^1.1.0",
37
40
  "mm_logger": "^1.0.0",
41
+ "mm_mod": "^1.0.2",
38
42
  "mm_mongodb": "^2.0.3",
39
- "mm_mqtt_server": "^1.0.2",
43
+ "mm_mqtt_server": "^2.0.0",
40
44
  "mm_mysql": "^2.5.6",
41
- "mm_param": "^1.1.0",
42
- "mm_pendant": "^1.1.0",
43
- "mm_plugin": "^1.0.0",
45
+ "mm_param": "^1.1.3",
46
+ "mm_pendant": "^1.1.1",
47
+ "mm_plugins": "^1.0.2",
44
48
  "mm_redis": "^2.1.7",
45
49
  "mm_render": "^1.0.0",
46
- "mm_socket_server": "^1.0.2",
47
- "mm_sql": "^1.8.0",
50
+ "mm_socket_server": "^3.0.0",
51
+ "mm_sql": "^1.8.2",
48
52
  "mm_sqlite": "^1.5.5",
49
- "mm_statics": "^1.9.0",
50
- "mm_timer": "^1.1.0",
51
- "mm_tpl": "^2.7.2",
52
- "mm_web_server": "^1.0.2",
53
- "mm_websocket_server": "^1.0.2"
53
+ "mm_statics": "^1.9.1",
54
+ "mm_template": "^1.2.1",
55
+ "mm_timer": "^1.4.4",
56
+ "mm_tpl": "^2.7.3",
57
+ "mm_web_server": "^2.0.1",
58
+ "mm_websocket_server": "^2.0.0"
54
59
  }
55
60
  }